问题描述
|
今天,我从切换块中得到了一些奇怪的行为,特别是我正在从文件中读取一个字节,并将其与某些十六进制值进行比较(文本文件编码问题,没什么大不了的)。该代码看起来像:
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-> int促销产生了0xffffffef而不是0x000000ef的情况吗?
解决方法
\“有人可以简要解释一下
继续进行char-> int促销
产生0xffffffef而不是
0x000000ef?\“
到目前为止,与这四个答案相反。
相反,您有一个
char
负值,作为switch
条件,该值升为与required3 required值相同的负int
值。
C ++ 98§6.4.2/ 2
进行整体促销。
然后,对于您的32位C ++编译器,ѭ4interpreted被解释为unsigned int
文字,因为对于32位int
而言,它太大了。
C ++ 98 2.13.1 / 2
如果是八进制或十六进制,并且没有后缀,则在
可以表示为:int
,unsigned int
,long int
,unsigned long int
。
现在,对于“ 11”标签,
C ++ 98§6.4.2/ 2
整数常量表达式(5.19)隐式转换为提升的
开关条件的类型。
在您的情况下,对于带符号的目标类型,转换的结果是正式实现定义的,方法是
C ++ 98§4.7/ 3
如果目标类型是带符号的,则该值可以表示,则保持不变
在目标类型(和位域宽度)中;否则,值为
实现定义的。
但是实际上,几乎所有编译器都使用二进制补码表示形式而没有任何陷阱,因此在您的情况下,实现定义的转换是将位模式0xffffffef
解释为负值的二进制补码规范。您可以通过0xffffffef-232来计算哪个值,因为我们在这里谈论的是32位表示形式。或者,由于这只是一个8位的值,已被符号扩展为32位,因此您也可以将其计算为0xef-28,其中0xef是字符代码点。
干杯,……
, 您的(已签名)字符的符号扩展为一个已签名的int。这是因为有符号的值以二进制存储的方式。
例
1 in二进制字符= 00000001
1 int int整数= 00000000 00000000 00000000 00000001
-1 in二进制字符= 11111111
二进制int中的-1不是00000000 00000000 00000000 11111111而是11111111 11111111 11111111 11111111
如果您转换回十进制,则应该预先知道要处理带符号还是无符号值,因为11111111的带符号的可能是-1,无符号的是255。
, platform1ѭ必须在您的平台上签名,并且您看到的是符号扩展名。
, 还没有说过(无论如何,我还是在键入),是否指定了char是未指定的。就您而言-如前所述-char是带符号的,因此任何大于127的ASCII值都将被解释为负数。
, 标志扩展