比较总是以 char 和常量失败
Posted
技术标签:
【中文标题】比较总是以 char 和常量失败【英文标题】:Comparison always fails with char and constant 【发布时间】:2016-03-28 19:54:57 【问题描述】:我试图比较一个字符串的第一个字符和一个十六进制常量来确定数据的类型。但每次都失败。谁能解释为什么下面的比较总是失败。
char charray[] = 0xAA, 0x00, 0x02;
char ch = charray[0];
if (0xAA == ch)
printf("Equal\n");
【问题讨论】:
【参考方案1】:问题出在这里:
char charray[] = 0xAA, 0x00, 0x02;
char 类型具有实现定义的符号,这意味着在某些系统上它将等同于signed char
。 signed char
最多只能存储 0x7F 的值,并且 MSB 将被视为符号位。这就是在您的情况下发生的情况,0xAA
被转换为 -86
的有符号值(它得到的值是由实现定义的,我假设是二进制补码)。
符号随后保留在表达式 0xAA == ch
中,因为 ch
随后被提升为类型 int
并且符号被保留。这意味着您实际上会比较 0xAA == -86
这是错误的。
为避免此类错误,在进行任何形式的字节级算术时,请始终使用uint8_t
。
【讨论】:
【参考方案2】:if (0xAA == ch)
假设char
是signed char
(char
的行为为signed char
或unsigned char
在C 中取决于实现),char
在==
表达式中提升为int
您实际比较的 32 位系统:
if (0xAA == 0xFFFFFFAA)
这是错误的。
防止符号扩展的一种方法是将右操作数强制转换为unsigned char
:
if (0xAA == (unsigned char) ch)
但最好在声明数组时使用unsigned char
。
【讨论】:
不,他实际上是在比较0xAA == -86
。不一定与0xAA == 0xFFFFFFAA
相同,具体取决于隐式促销在特定系统上的结果。
@Lundin 如果你想挑剔的话,他实际上是在比较 0xAA == (signed char) 0xAA
这甚至是不同的,因为转换是实现定义的。
我的意思是:只要左操作数(int 字面量)是int
,那么 char 只会经过整数提升(整数提升规则)并保持有符号。但是如果文字是无符号类型,也会有平衡(通常的算术转换),并且正确的操作数也会被转换为无符号类型。在这种情况下,您实际上最终会等于0xFFFFFFAAu
。但这在这个特定的例子中不会发生。
@Lundin 如果左操作数是unsigned int
,那么ch
在最终转换为unsigned int
之前仍将提升为int
。【参考方案3】:
0xAA
是一个 int
文字。 char
可以在您的系统上签名或未签名。 C 标准允许两者之一。
在 0xAA == ch
中,ch
被提升为 int
类型,比较结果为 0。
【讨论】:
以上是关于比较总是以 char 和常量失败的主要内容,如果未能解决你的问题,请参考以下文章