我今天从交换机块中获得了一些奇怪的行为,特别是我从文件中读取一个字节并将其与某些十六进制值进行比较(文本文件编码问题,没什么大不了的)。代码看起来像:
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促销?
答案 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
如果它是八进制或十六进制且没有后缀,则它具有第一种类型 它可以代表:int
,unsigned int
,long int
,unsigned 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。,