在unsigned char到整数类型转换的背景下发生了什么?

时间:2011-06-06 20:43:01

标签: c++ binary casting implicit-conversion

我今天从交换机块中获得了一些奇怪的行为,特别是我从文件中读取一个字节并将其与某些十六进制值进行比较(文本文件编码问题,没什么大不了的)。代码看起来像:

char BOM[3] = {0};
b_error = ReadFile (iNCfile, BOM, 3, &lpNumberOfBytesRead, NULL); 

switch ( BOM[0] ) {
case 0xef: {
    // Byte Order Marker Potentially Indicates UTF-8
    if ( ( BOM[1] == 0xBB ) && ( BOM[2] == 0xBF ) ) {
        iNCfileEncoding = UTF8;
    }
    break;
           }
}

虽然调试看起来不错,但哪个不起作用。我意识到交换机正在将值提升为整数,一旦点击到位,我就可以在case语句中使用0xffffffef进行匹配。当然,正确的解决方案是使BOM []无符号,现在所有内容都按预期进行推广和比较。

有人可以简单解释一下char中发生了什么 - >产生0xffffffef而不是0x000000ef的int促销?

5 个答案:

答案 0 :(得分:3)

你的(签名)字符的符号被扩展为形成一个签名的int。这是因为有符号值以二进制形式存储的方式。

实施例

1 in binary char = 00000001

1 in binary int = 00000000 00000000 00000000 00000001

-1 in binary char = 11111111

二进制int中的

-1不是00000000 00000000 00000000 11111111但是11111111 11111111 11111111 11111111

如果你转换回十进制,你应该事先知道你是在处理有符号值还是无符号值,因为11111111在签名时可能是-1而在无符号时可能是255。

答案 1 :(得分:3)

char必须在您的平台上签名,您所看到的是sign extension

答案 2 :(得分:2)

尚未陈述的内容(无论如何,我输入)是指未定义char是否被烧焦。在您的情况下 - 如上所述 - char已签名,因此任何高于127的ASCII值都将被解释为否定。

答案 3 :(得分:1)

答案 4 :(得分:1)

  

“有人可以简单地解释一下是什么   继续在char - >促销   那产生了0xffffffef而不是   0x000000ef?“

与目前为止的四个答案相反, 它没有。

相反,您有一个负char值,其switch条件被提升为

所需的相同负int
  

C ++98§6.4.2/ 2
  进行整体促销。

然后,您的32位C ++编译器0xffffffef被解释为unsigned int字面值,因为它对于32位int来说太大了,

  

C ++ 98 2.13.1 / 2
  如果它是八进制或十六进制且没有后缀,则它具有第一种类型   它可以代表:intunsigned intlong intunsigned long int

现在,对于case标签,

  

C ++98§6.4.2/ 2
  积分常量表达式(5.19)隐式转换为提升   开关条件的类型。

在您的情况下,使用签名目标类型,转换结果由

正式实现定义
  

C ++98§4.7/ 3
  如果目标类型已签名,则如果可以表示该值,则该值不变   在目标类型(和位字段宽度);否则,价值是   实现定义的。

但实际上几乎所有的编译器都使用了两个补码表示而没有陷阱,因此实现定义的转换就是在你的情况下,bitpattern 0xffffffef被解释为负值的二进制补码。您可以通过0xffffffef - 2 32 来计算哪个值,因为我们在这里讨论的是32位表示。或者,因为这只是一个8位的值符号扩展到32位,你可以选择将其计算为0xef - 2 8 ,其中0xef是字符代码点。

干杯&第h。,