在最后一天,我的代码中有一个讨厌的错误,经过一些搜索似乎与char值和hex之间的比较有关。我的编译器是在Windows上运行的gcc 4.4.1。 我在下面的简单代码中复制了这个问题:
char c1 = 0xFF; char c2 = 0xFE;
if(c1 == 0xFF && c2 == 0xFE)
{
//do something
}
令人惊讶的是,上面的代码没有进入循环。我完全不知道为什么,并且真的很感激一些帮助。如此荒谬,解决方案必须(一如既往)是我完全忽视的一个巨大错误。
如果我用无符号字符替换上面的字符,它可以工作,但仅限于某些情况。我正在努力找出发生了什么。另外,如果我将十六进制值转换为char,它会正确地进入循环:
if(c1 == (char)0xFF && c2 == (char)0xFE)
{
//do something
}
这是什么意思?它为什么会发生?原始十六进制值是否默认解释为char? 对于我的代码中的好奇点,我首先注意到它是一个流的前2个字节与上面的十六进制值的比较,以及它们与字节顺序标记的相反。
感谢任何帮助
答案 0 :(得分:8)
普通char
可以是signed
或unsigned
。如果类型为unsigned
,则所有内容均按您的预期运行。
如果类型为signed
,则将0xFF分配给c1
意味着在执行比较时该值将被提升为-1
,但0xFF是常规正整数,因此比较-1 == 0xFF
的失败。
请注意,char
,signed char
和unsigned char
类型是不同的,但其中两个具有相同的表示形式(两个中的一个是char
)。< / p>
答案 1 :(得分:4)
文字0xff
不是char
,而是int
(已签名)。当你把它变成char
变量时,它会适合,但是,根据你的char
类型是签名还是未签名,这将影响它在表达式中的升级方式(见下文)。
在if (c1 == 0xff)
之类的表达式中,c1
变量将被提升为整数,因为0xff
是signed char
。 它被提升为取决于它是否已签名。
最重要的是,你可以做两件事之一。
确保您使用int
,以便“签名延伸”到正确的0xff
。我的意思是一个未签名的字符int
将成为(对于一个4字节0x000000ff
)0xffffffff
(所以它仍然是255)但签名的字符将成为(char)oxff
(所以它仍然是-1)。
将文字Shoehorn变为与变量相同的类型,您已经使用{{1}}进行了。
答案 2 :(得分:4)
将char与hex进行比较时,必须小心:
Using the == operator to compare a char to 0x80 always results in false?
我建议在C99中引入这种语法以确保
if(c1 == '\xFF' && c2 == '\xFE')
{
// do something
}
避免演员表演,这是不必要的,并且不是安全的。
它告诉编译器0xFF是char而不是int,这将解决你的问题。
clang编译器也会警告你:
将常数128与类型&#39; char&#39;的表达式进行比较总是假的[-Werror,-Wututological-constant-out-of-range-compare]
答案 3 :(得分:0)
字符0xFE将转换为负整数。表达式中的常量将转换为正整数。
答案 4 :(得分:0)
我通过将变量转换为UINT16(针对我的编译器进行了优化)解决了这个问题。在您的情况下,您将c1和c2转换为INT
char c1 = 0xFF; char c2 = 0xFE;
if((int)c1 == 0xFF && (int)c2 == 0xFE)
{
//do something
}