如何将char转换为unsigned int?

12

我有一个字符数组,实际上是用作字节数组而不是用来存储文本。在该数组中,有两个特定的字节表示我需要存储为无符号整数值的数字值。以下代码解释了设置。

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。但我在我的无符号整数中得到的是0xffffffbc

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


1
你不应该使用指针,因为 unsigned int 的大小可能与 char[2] 不同。 - Mooing Duck
5个回答

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

如果sizeof(unsigned int) >= 2 * sizeof(unsigned char)(这不是C标准保证的内容)

现在... 这里有趣的事情显然是运算符的顺序(多年来,我仍然只记得+-*/...真羞愧:-),所以我总是尽可能地加上括号。 []最重要。第二个是(cast)。第三个是<<,第四个是|(如果你使用+代替|,请记住+<<更重要,所以你需要加上括号)。

我们不需要将两个(unsigned char)向上转换为(unsigned integer),因为存在整数提升,它将为我们完成其中一个,而对于另一个,则应该自动执行算术转换

我要补充的是,如果你想少些头疼:

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

到目前为止,唯一正确的答案。不过,将其转换为“unsigned int”是不必要的。 - Oliver Charlesworth
1
在最后一行中,val |= ... 可能更快。 - Mooing Duck
你的第一行代码已经解决了问题。然而,在发布这个问题之前,我也尝试过最后一个片段。那是一个根本没有起作用的“解决方案”。 - RLH

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

1
@MooingDuck,我确实错过了强制类型转换,但是<<的优先级高于|,所以在我的版本中不需要括号。 - Jens Erat

2

字节序取决于处理器的字节顺序。您可以执行以下操作,在大端或小端机器上均可正常工作。(如果没有ntohs,它将在大端上工作):

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

我认为那不会起作用,因为ntohs将读取过多的字节。 - Mooing Duck
@MooingDuck,它会起作用的,ntohs是用于16位值的。ntohl是用于32位的。 - TJD
哦,正确。但是 *(unsigned int*)bytes 会读取太多字节。 - Mooing Duck
1
更好了,但可能会出现对齐问题。等等,我觉得这个问题与字节序无关... - Mooing Duck
如果您将16位指针映射到它上面,就必须考虑字节序问题。在小端模式下执行*(uint16_t*)操作时,val == 0x880C。在大端模式下,val == 0xC88。对齐点是正确的,但现在很难找到一个处理器不能进行未对齐访问,即使在嵌入式领域也是如此。 - TJD
@TJD:这并不难。例如,对于DSP ISA而言,不支持非对齐访问是相当常见的。 - Oliver Charlesworth

0
unsigned int val = bytes[0] << 8 + bytes[1];

1
我忍不住了...它是如此的黑白 :-) - xanatos
3
严格来说,当bytes[0]的最高位设置时,这将导致整数溢出(如果char默认为signed)。 - Oliver Charlesworth
1
我要补充一下,有半公里长的警告。标准中没有写字节只有8位。 - xanatos
@Banthar:虽然从可读性角度来看,加上括号可能更好,但你并不需要它们。 - Oliver Charlesworth
1
事实上,我撤回早先的评论!如果“char”是“signed”,它根本无法正常工作。 - Oliver Charlesworth
显示剩余2条评论

0

我认为这是一个比依赖指针别名更好的方法:

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

严格来说,这仍然依赖于类型别名。 - Oliver Charlesworth
@MooingDuck:C99允许通过联合类型进行类型转换-在2007年的TC3中,已经在6.5.2.3节中添加了明确说明的脚注;但是,Chuck的代码假定小端字节顺序-移位是可移植的解决方案。 - Christoph
@Christoph:在C++中是非法的,这是我的错误。在它被编辑之前,我无法删除我的-1 :( - Mooing Duck
@MooingDuck:添加了一个缺失的分号,所以可以开始了 ;) - Christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接