【问题标题】:How can I cast a char to an unsigned int?如何将 char 转换为 unsigned int?
【发布时间】:2011-12-15 03:22:41
【问题描述】:

我有一个真正用作字节数组而不是用于存储文本的 char 数组。在数组中,有两个特定字节表示我需要存储到无符号 int 值中的数值。下面的代码解释了设置。

char* bytes = bytes[2];
bytes[0] = 0x0C; // For the sake of this example, I'm 
bytes[1] = 0x88; // assigning random values to the char array.

unsigned int val = ???; // This needs to be the actual numeric 
                        // value of the two bytes in the char array.  
                        // In other words, the value should equal 0x0C88;

我不知道该怎么做。我认为这将涉及指针的一些转换和重铸,但我无法让它工作。我怎样才能实现我的最终目标?

更新

感谢 Martin B 的快速响应,但这不起作用。具体来说,就我而言,这两个字节是0x000xbc。显然我想要的是0x000000bc。但是我在 unsigned int 中得到的是0xffffffbc

Martin 发布的代码是我的实际原始代码,只要所有字节都小于 128(即正符号字符值),它就可以正常工作。

【问题讨论】:

  • 您不会想要使用指针,因为unsigned int 的大小不太可能与char[2] 相同。

标签: c pointers casting


【解决方案1】:
unsigned int val = (unsigned char)bytes[0] << CHAR_BIT | (unsigned char)bytes[1];

这 if sizeof(unsigned int) &gt;= 2 * sizeof(unsigned char)(不是 C 标准所保证的)

现在...这里有趣的事情肯定是运算符的顺序(多年来我仍然只记得+, -, * and /...真丢人:-),所以我总是尽可能多地放括号)。 [] 为王。其次是(cast)。第三个是&lt;&lt;,第四个是|(如果你使用+而不是|,请记住+&lt;&lt;更重要,所以你需要刹车)

我们不需要向上转换到(unsigned integer) 这两个(unsigned char),因为有一个integral promotion 会为我们做这件事,而另一个应该是自动的Arithmetic Conversion

如果你想减少头痛,我会补充一点:

unsigned int val = (unsigned char)bytes[0] << CHAR_BIT;
val |= (unsigned char)bytes[1];

【讨论】:

  • +1:到目前为止唯一正确的答案。不过,不需要强制转换为 unsigned int
  • 在最后一行,val |= ... 可能更快。
  • 您的第一行代码已经解决了问题。但是,在发布此问题之前,我也尝试了最后一个 sn-p。那是一个根本行不通的“解决方案”。
【解决方案2】:
unsigned int val = (unsigned char) bytes[0]<<8 | (unsigned char) bytes[1];

【讨论】:

  • @MooingDuck 我确实错过了选角,但
【解决方案3】:

字节顺序取决于处理器的字节顺序。您可以这样做,这将适用于大端或小端机器。 (如果没有 ntohs,它将适用于大端):

unsigned int val = ntohs(*(uint16_t*)bytes)

【讨论】:

  • 我认为这行不通,因为 ntohs 会读取太多字节。
  • @MooingDuck,它会工作,ntohs 适用于 16 位值。 ntohl 适用于 32 位
  • 哦,正确。但是,*(unsigned int*)bytes 会读入太多字节。
  • 更好,但这可能会出现对齐问题。等等,我认为这个问题与字节序无关......
  • 如果您将 16 位指针映射到它,您必须担心字节顺序。如果您在 little endian 上执行 (uint16_t),则 val == 0x880C。在大端,val == 0xC88。对齐点是正确的,但现在很难找到不能进行非对齐访问的处理器,即使在嵌入式世界中也是如此。
【解决方案4】:
unsigned int val = bytes[0] << 8 + bytes[1];

【讨论】:

  • 我无法抗拒......它是如此的黑白:-)
  • 严格来说,当bytes[0]的msb被设置时,这将引发整数溢出(如果char默认为signed)。
  • 我要补充一点,有半公里长的警告。在标准中没有任何地方写到一个字节只有 8 位:-)
  • @xanatos,没有意识到 `` 和 4spaces 格式的代码不同
  • 事实上,我撤回了我之前的评论!如果charsigned,它将无法正常工作。
【解决方案5】:

我认为这比依赖指针别名更好:

union {unsigned asInt; char asChars[2];} conversion;
conversion.asInt = 0;
conversion.asChars[0] = 0x0C;
conversion.asChars[1] = 0x88;
unsigned val = conversion.asInt;

【讨论】:

  • 严格来说,这仍然依赖于类型别名。
  • @MooingDuck:C99 允许通过联合进行类型双关语 - 2007 年在 TC3 的第 6.5.2.3 节中添加了一个明确说明这一点的脚注;但是,Chuck 的代码采用 little-endian 字节顺序 - 移位是可移植的解决方案
  • @Christoph:这在 C++ 中是非法的,我的错。在编辑之前我无法删除我的 -1 :(
  • @MooingDuck:添加了一个缺少的分号,所以开火吧 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2012-04-28
  • 1970-01-01
相关资源
最近更新 更多