【问题标题】:How to convert a char[2] to a unsigned short in C?如何在 C 中将 char[2] 转换为 unsigned short?
【发布时间】:2013-12-12 01:26:01
【问题描述】:

我在转换数据时遇到问题。

我得到了一个特定的字符串(它实际上只代表一些数据位(小端序),而不是文本):

char freeBlockSize[2];

我想把它转换成这种类型:

unsigned short numOfBlocks;

我一直在尝试以下代码,但它似乎打印垃圾,因为每次我运行它时,“numOFBlocks”的值都会得到不同的输出(freeBlockSize 是由另一个函数提供给我的,并且始终是同样):

unsigned short numOFBlocks = (unsigned short)freeBlockSize;

printf("Test: %d %d\n",freeBlockSize[0],freeBlockSize[1]);
printf("Value: %hu\n",numOFBlocks);

提前感谢您的帮助。

【问题讨论】:

  • “另一个函数”的short是如何编码的?字节序是否得到保证,还是实现定义?
  • 哦,它是小端序。我会更新问题。

标签: c type-conversion unsigned


【解决方案1】:

用途:

  unsigned short numOFBlocks = *(unsigned short *)freeBlockSize;

但要小心:如果您在freeBlockSize 中拥有的数据的字节序与您的机器的字节序相同,这将起作用,这可能是也可能不是,具体取决于存储在该向量中的数据源.


更新:使用这种方法访问未对齐的指针存在一定的风险,所以这里有另一种方法可以规避这个问题:

unsigned short numOfBlocks = ((freeBlockSize[1] << 8) &0xFF00) | (freeBlockSize[0] & 0xFF);

这会将 freeBlockSize 指向的 16 位数字作为 LE 数字,并将其以主机端格式存储到 numOfBlocks 中。前一种方法没有考虑主机端,因此只有在freeBlockSize中存储的数据与主机数据格式相同时才有效。

【讨论】:

  • 如果freeBlockSize 未正确对齐short,这将在某些平台上崩溃。
  • 效果很好,谢谢。顺便说一句,我已经更新了问题,日期以小端格式出现,但它似乎转换得很好。有什么方法可以让我对在不同计算机上运行的代码感到安全吗?这不会只靠我自己运行。
【解决方案2】:

如果您希望能够以不同的值访问相同的内存,union 就可以了。

union short_bytes {
    unsigned short shorty;
    char bytes[2];
};
...
union short_bytes foo;

foo.shorty = (unsigned short)freeBlockSize;

printf("Test: %hhd %hhd\n", foo.bytes[0], foo.bytes[1]);
printf("Value: %hu\n", foo.shorty);

【讨论】:

    【解决方案3】:

    遇到类似问题后,我发现 char 是有符号类型。因此,要将 char 类型用作数字,请将您的变量或数组声明为“unsigned char” 那么当你将其转换为更长的类型(例如 unsigned short)时,它会正确转换。

    【讨论】:

      【解决方案4】:

      让编译器优化处理细节。

      // OP says little endian.
      #include <limits.h>
      numOfBlocks = (unsigned char) freeBlockSize[1];
      numOfBlocks <<= CHAR_BIT;  // thanks @Dietrich Epp 
      numOfBlocks += (unsigned char) freeBlockSize[0];
      

      由于 OP 现在说小端(与网络顺序匹配)并且字节序和可移植性受到关注,请考虑在 `*(unsigned short *)freeBlockSize` 之后使用:

      #include <netinet/in.h>
      uint16_t htons(uint16_t hostshort);
      uint16_t ntohs(uint16_t netshort);
      

      【讨论】:

      • &lt;&lt;= CHAR_BIT 不是*=
      【解决方案5】:

      抛开字节序问题不谈,就像将保存char[] 数组的内存重新解释为保存short 一样简单:

      char freeBlockSize[2];
      unsigned short res;
      // ..code..
      res=*(unsigned short *)freeBlockSize;
      

      顺便说一下,假设您正在使用某个函数并将char[2] 作为结构内的字段传递,您可以将您身边的结构定义为具有unsigned short 字段而不是(或联合如果您确实需要明确地需要 2 个字节,则两者中的一个)。这可以让您避免额外的步骤。

      【讨论】:

      • 如果freeBlockSize 未正确对齐short,这将在某些平台上崩溃。
      • 我相信你的意思是freeBlockSize 而不是&amp;freeBlockSize
      • 对齐与它有什么关系?
      • @Blindy 如果freeBlockSize 数组存在于奇数地址上,在不接受奇数地址上的short 的系统上,此代码将出现段/总线故障。
      • 喜欢..?请记住,我们是在 2013 年,距离 16 位受保护内存模型热潮过去几年。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-16
      • 2015-01-20
      • 1970-01-01
      相关资源
      最近更新 更多