将字符与十六进制值进行比较

时间:2012-01-13 07:19:46

标签: c hex

在最后一天,我的代码中有一个讨厌的错误,经过一些搜索似乎与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个字节与上面的十六进制值的比较,以及它们与字节顺序标记的相反。

感谢任何帮助

5 个答案:

答案 0 :(得分:8)

普通char可以是signedunsigned。如果类型为unsigned,则所有内容均按您的预期运行。 如果类型为signed,则将0xFF分配给c1意味着在执行比较时该值将被提升为-1,但0xFF是常规正整数,因此比较-1 == 0xFF的失败。

请注意,charsigned charunsigned char类型是不同的,但其中两个具有相同的表示形式(两个中的一个是char)。< / p>

答案 1 :(得分:4)

文字0xff不是char,而是int(已签名)。当你把它变成char变量时,它会适合,但是,根据你的char类型是签名还是未签名,这将影响它在表达式中的升级方式(见下文)。

if (c1 == 0xff)之类的表达式中,c1变量将被提升为整数,因为0xffsigned char它被提升为取决于它是否已签名。

最重要的是,你可以做两件事之一。

  1. 确保您使用int,以便“签名延伸”到正确的0xff。我的意思是一个未签名的字符int将成为(对于一个4字节0x000000ff0xffffffff(所以它仍然是255)但签名的字符将成为(char)oxff(所以它仍然是-1)。

  2. 将文字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
}