根据 PC-lint ,以下声明永远不会是TRUE
:
if((variable & 0x02) == 1)
我正在为嵌入式系统使用C编译器,只要TRUE
中的相应位置位,就会将其评估为variable
。我想编译器正在对TRUE
的两边进行FALSE
/ ==
比较,而不是比较得到的数字。换句话说,每次表达式(varable & 0x02)
不为零(即TRUE
)时,语句也将为TRUE
,因为值1 is also TRUE
(非零)。 / p>
我不知道C/C++
标准是否清楚地定义了编译器在这种情况下的行为方式。是否有C/C++
位专家可以根据标准(例如C90, C99,
等)的说法回答这个问题?
P.S。:在上面的陈述中,“variable”是一个unsigned char。
答案 0 :(得分:11)
PC-lint是对的。假设var
是一个整数变量,表达式var & 0x02
可以计算为两个值:0
和2
。它永远不会等于1
,这是if
语句正在测试的内容。
为了对此进行扩展,将等于运算符应用于两个整数值。重要的是两个操作数是否评估相同的数字,而不是它们是否同时“真实”或“错误”。
要测试是否设置了位1,可以使用:
if (variable & 0x02) {
...
}
鉴于您的编译器的行为与您所说的一样,它显然是不合规的。但是,它几乎肯定会正确处理if (variable & 0x02)
。我的建议是修复代码,这样如果你要更改编译器,它就不会默默地破坏。
最后,如果出现以下情况则情况不同:(1)代码是C ++而不是C; (2)variable
是一个类的实例; (3)该类使有问题的运算符超载。在这种情况下,行为可以归结为重载运算符实际执行的操作。
答案 1 :(得分:6)
在C ++中,如果(且仅当)variable
是具有重载operator&
且不符合正常按位AND语义的类的实例,则可以求值为真值。
在C中,这种情况总是错误的。 §6.5.10定义了按位AND运算符的语义,它非常简单,重点突出:
4.二进制&的结果operator是操作数的按位AND(也就是每个位 当且仅当转换的操作数中的每个相应位都是时,才设置结果 设定)。
很明显,结果不能为1,因为在右侧操作数的转换值中没有设置1位(即0x02
)。
当然,如果在程序过去(或编译时)的某个时刻调用了未定义的行为,那么任何事情都可能发生。但是,除非存在这种可能性,否则您的编译器不符合要求。也就是说,破碎了。不幸的是,这在奇数嵌入式编译器上非常非常常见。如果你很幸运,你甚至可以报告错误并修复它。
答案 2 :(得分:4)
我不认为该标准对这个非常具体和不寻常的问题有任何定义。正如aix所说,该陈述永远不会成立,因为(二进制):
XXXX XXXX -> variable
0000 0010 -> 0x02
--------- AND
0000 00X0 -> result
(简化为8位类型)
所以你唯一的结果可能是0000 0010(即2)或0000 0000(即0)。
答案 3 :(得分:1)
对于C,答案是否定的。
C standard说&
(6.5.10):
二进制&的结果operator是操作数的按位AND(也就是每个位 当且仅当转换的操作数中的每个相应位都是时,才设置结果 设定)。
因为在2
中只设置了位1,所以表达式的值只能设置位1.它不能使用除2和0之外的其他值.2和0都不能比较等于1
整数的位表示在6.2.6.2中定义(对于通常方式的非负值)。
答案 4 :(得分:0)
基本上,lint就在这里。至少在我所知道的任何平台上,这种情况都会产生错误。查看数字的位表示:x&对于任何整数x,2(0010)将始终为0或2(0010),因此不同于1(0001)。
答案 5 :(得分:0)
让我们考虑二进制值2
02 = 0010 (say a 4 bit number)
,二进制值为1
01 = 0001
2的最小有效位始终为零,即最左边的位为0. SO
& (和)0的操作从不给1,因此我们可以说它永远不会等于1
0 0 => 0
0 1 => 0
1 1 => 1
注意:&表示位和操作
2 - 0010
3 - 0011
0010
所以输出xx& 2将为0或2。