C语言中的条件语句是否总是返回1或0?

10
C语言中的条件语句是否总是返回[1或0],还是返回[0或“非零值”]?我问这个问题是因为:
伪代码 -
foo(address, shouldSend): register >>= 1 register <<= 1 //清除第一个位置上的位 register |= shouldSend //用于标记它是否应该发送
如果有人传递了一个大于1的true值给shouldSend(因为只有0是false,其他所有值都是true,从技术上讲这是有效的),就会出现问题。由于我直接将shouldSend的真值与寄存器进行OR运算,所以最好不要是0xFF!我已经有了解决方案,所以问题更多是出于好奇。但我想知道的是:
foo(address, shouldSend): register >>= 1 register <<= 1 // to clear bit in first position register |= (shouldSend > 0) //用于标记它是否应该发送
能否解决这个问题?我认为现在C条件语句掩盖了传入的0xFF(或一般来说是大于1的值)的问题。但是这仅在C条件语句保证返回[0或1]的情况下成立。
PS- 我也意识到这可能与编译器有关,但ANSI标准对此有何说法?

应该是(shouldSend!= 0)吧?使用!!shouldSend是一种不好的技巧。 - Hans Passant
4个回答

23

标准规定结果始终是整数值,等于0或1。

6.5.8 关系运算符

每个运算符 <(小于)、>(大于)、<=(小于或等于)和 >=(大于或等于)应在指定的关系为真时返回1,在假时返回0。92)结果类型为int。


1
+1,非常惊讶它确实指定了这种行为。随着时间的推移,我只是假设规范更有可能说“返回0或随机结果”。 - JaredPar
2
这就导致了一个成语,我在标准出现之前就看到过:!!somevalue 它具有相同的真值,但现在保证它恰好为0或1。 - RBerteig

1

与其进行右移和左移操作以清除最低有效位,不如使用按位与运算符0xFE:

register = register & 0xFE;

[编辑:假设寄存器为8位。如果不是,请根据需要调整右手操作数]

但是,如果shouldSend是条件测试的结果,则标准保证它只能是0或1。如果对于shouldSend是否可能来自其他地方存在任何疑问,最好像您所做的那样采取预防措施,或者类似的方法。

register = register | (shouldSend ? 1 : 0);

1
在标准出现之前,我见过使用的习语是!!somevalue,它具有相同的真值,但现在保证确切为0或1。 - RBerteig

1

无论是否指定,最好始终针对false进行测试,并明确您的或等值。这样可以消除对编译器实现的任何担忧,并且更清晰、更易于维护。


这实际上是相关的,因为您可以使用&和|运算符作为逻辑运算符,而不会出现短路。 - Spidey

0

是的。在C99中,这是有保证的。我手头没有C89规范。当然,编译器实现者偶尔会犯错误,所以结果可能会有所不同。

C99在6.5.8关系运算符的第6段中指定了以下内容:

如果指定的关系为真,则每个运算符<(小于)、>(大于)、<=(小于或等于)和>=(大于或等于)应返回1;如果指定的关系为假,则应返回0。

相同或类似的条款出现在6.5.9相等运算符的第3段、6.5.13逻辑AND运算符的第3段和6.5.14逻辑OR运算符的第3段中。


这在最初的K&R C中是正确的,通常取决于此,因此标准必须跟随其后。 - RBerteig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接