C标准是否明确地将真值指示为0或1?

时间:2016-05-18 06:19:26

标签: c

我们知道任何不等于0的数字在C中都被视为true,因此我们可以写:

int a = 16;

while (a--)
    printf("%d\n", a);  // prints numbers from 15 to 0

但是,我想知道在C中将true / false定义为1 / 0,所以我尝试了下面的代码:

printf("True = %d, False = %d\n", (0 == 0), (0 != 0));  // prints: True = 1, False = 0

C标准是否分别明确指出真值和真值10

7 个答案:

答案 0 :(得分:91)

  

C标准是否分别明确指出truefalse的真值为01

C标准将truefalse定义为stdbool.h中的宏,分别扩展为10

C11-§7.18:

  

其余三个宏适用于#if预处理指令。他们是

true
     

扩展为整数常量1

false
     

扩展为整数常量0 [...]

关于运营商==!=

C11-§6.5.9/ 3:

  

==(等于)和!=(不等于)运算符类似于关系运算符,除了它们的优先级较低。 108)每个运算符如果指定的关系为真,则生成1;如果为假,则生成0。结果的类型为int。对于任何一对操作数,其中一个关系是正确的。

答案 1 :(得分:50)

在C11中没有明确指出。所有语言级操作将返回1作为真值(并接受任何非零,包括NaN为真)。

  • 如果您关注_Bool,则true必须为1,因为标准只要求它保持0和1.(§6.2.5/ 2)。
  • 同样在<stdbool.h>中,宏true扩展为1(§7.18/ 3)
  • ==!=<><=>=返回0或1(§6.5.8/ 6, §6.5.9/ 3)。
  • !&&||返回0或1(§6.5.3.3/ 5,§6.5.13/ 3,§6.5.14/ 3)
  • defined扩展为0或1(§6.10.1/ 1)

但所有标准库函数,例如islower只是说“非零”(例如§7.4.1/ 1,§7.17.5.1/ 3,§7.30.2.1/ 1,§7.30.2.2.1/ 4)。

  

§6.2.5/ 2 :声明为_Bool类型的对象足以存储值0和1。

     

§6.5.5.3/ 5 :如果操作数的值不等于0,则逻辑否定运算符!的结果为0;如果其操作数的值为1,则为1等于0. ...

     

§6.5.8/ 6 :每个运算符<(小于),>(大于),<=(小于或等于),>=(大于或等于)如果指定的关系为真,则产生1,如果为假,则产生0。 107)...

     

§6.5.9/ 3 ==(等于)和!=(不等于)运算符类似于关系运算符,除了它们的优先级较低.108)如果指定的关系为真,则每个运算符产生1,如果为假,则产生0。 ...

     

§6.5.13/ 3 :如果&&运算符的两个操作数都不等于0,则||运算符将产生1; ...

     

§6.5.14/ 3 defined identifier运算符如果其任一操作数比较不等于0,则应得1; ...

     

§6.10.1/ 1 :...它可能包含表单的一元运算符表达式 - defined ( identifier ) - 或 - #if - 如果......评估为1      

§7.4.1(字符分类函数)/ 1 :当且仅当...

时,本子句中的函数返回非零(true)      

§7.18/ 3 :其余三个宏适用于true预处理指令。它们是 - atomic_is_lock_free - 扩展为整数常量1,...

     

§7.17.5.1/ 3 :当且仅当对象的操作无锁时,iswctype泛型函数才返回非零(true)。 ...

     

§7.30.2.1(宽字符分类函数)/ 1 :当且仅当...

时,本子句中的函数返回非零(true)      

§7.30.2.2.1/ 4 :当且仅当... {/ p>时,=IFS(COUNTIFS('DATA'!$A:$A,$A17,'DATA'!$M:$M,"02 - B")=0,"0",(COUNTIFS('DATA'!$A:$A,$A17,'DATA'!$C:$C,"A - Open",'DATA'!$M:$M,"02 - B"))>0,"1",(COUNTIFS('DATA'!$A:$A,$A17,'DATA'!$C:$C,"A - Open",'DATA'!$M:$M,"02 - B")=0) **(This is where I get stucK) &** ((COUNTIFS('DATA'!$A:$A,$A17,'DATA'!$C:$C,"D - Closed",'DATA'!$M:$M,"02 - B"))<(COUNTIFS('DATA'!$A:$A,$A17,'DATA'!$M:$M,"02 - B"))),"2") 函数返回非零(true)

答案 2 :(得分:21)

在C中处理布尔值(我的意思是真/假值而不是特定的C bool/_Bool类型)时,需要注意两个标准区域。

第一个与表达式的结果有关,可以在C11 6.5 Expressions的各个部分找到(例如,关系运算符和相等运算符)。最重要的是,每当表达式生成布尔值时,它就......

  

...如果指定的关系为真,则产生1,如果为假,则产生0。结果的类型为int。

所以,是的,任何生成布尔的表达式的结果都是一个表示true,或者表示false表示false。这与stdbool.h中的内容相符,标准宏truefalse的定义方式相同。

请记住,遵循“你所发送的保守,你所接受的自由”的健全性原则,布尔上下文中对整数的解释稍微放松一些。 / p>

同样,从6.5的各个部分,你会看到如下语言:

  

||运算符如果其操作数比较不等于0,则产生1;否则,它产生0。结果的类型为int。

从那个(和其他部分),很明显零被认为是假的,而任何其他值都是真的。

另外,指定用于布尔生成和解释的值的语言也会出现在C99和C89中,所以它们已经存在了很长时间。甚至K&amp; R(ANSI-C第二版第一版)也指定了以下文本段:

  

i > j之类的关系表达式和&&以及||连接的逻辑表达式被定义为如果为true则值为1,如果为false则为0。< / p>      

ifwhilefor等的测试部分中,“true”仅表示“非零”。

     

&&运算符...如果两个操作数的比较不等于零,则返回1,否则返回0。

     

||运算符...如果其操作数比较不等于零,则返回1,否则返回0。

stdbool.h中的宏也会出现在C99中,但不会出现在C89或K&amp; R中,因为那时头文件不存在。

答案 3 :(得分:8)

你混合了许多不同的东西:控制语句,运算符和布尔类型。每个人都有自己的规则。

控制语句的作用类似于if语句,C11 6.4.8.1:

  

在两种形式中,如果表达式,则执行第一个子语句   比较不等于0。

whilefor等具有相同的规则。这与&#34; true&#34;无关。或&#34; false&#34;。

对于应该产生布尔结果的运算符,它们实际上产生值为1或0的int。例如,相等运算符,C11 6.5.9:

  

如果指定的关系为真且0为0,则每个运算符的结果为1   如果是假的

以上所有是因为C在1999年之前没有布尔类型,即使它确实得到一个,上述规则也没有改变。因此,与语句和运算符产生布尔类型(如C ++和Java)的大多数其他编程语言不同,它们只产生int,值为零或不为零。例如,sizeof(1==1)将在C中给出4,但在C ++中给出1。

C中的实际布尔类型名为_Bool,需要现代编译器。标头stdbool.h定义了宏booltruefalse,分别扩展为_Bool10(与C ++的兼容性。)

然而,将控制语句和运算符视为实际需要/产生布尔类型是一种很好的编程习惯。像MISRA-C这样的某些编码标准推荐这种做法。那就是:

if(ptr == NULL)代替if(ptr)

if((data & mask) != 0)代替if(data & mask)

这种风格的目的是借助静态分析工具提高类型安全性,从而减少错误。可以说,这种风格只有在你使用静态分析仪时才有意义。虽然在某些情况下它会导致更具可读性,自我记录的代码,例如

if(c == '\0') 

很好,意图很明确,代码是自我记录的。

if(c) 

坏。可能意味着什么,我们必须寻找c的类型来理解代码。它是整数,指针还是字符?

答案 4 :(得分:3)

我用多种语言编程。我看到真的是1或-1取决于语言。真实存在1的逻辑是有点是0或1.真正的-1背后的逻辑是!运营商是一个补充。它将所有的1改为0,将0的所有0改为1。所以,对于一个int,!0 = -1和!( - 1)= 0.这已经使我绊倒了以至于我没有将某些东西比作== true,而是将它比作是!= false。这样,我的编程风格适用于所有语言。所以我的答案是不要担心它,但编程使你的代码能够正常工作。

答案 5 :(得分:1)

需要更仔细地研究这个答案。

C ++中的实际定义是任何不为0的东西都被视为true。为什么这有关系?因为C ++不知道我们如何思考它是一个整数是什么 - 我们创造了这个意义,它所拥有的只是shell和规则意味着什么。它知道什么位,组成一个整数。

1作为一个整数松散地用比特表示,比如8比特的符号int表示0000 0001.我们在视觉上看到的很多次是一个谎言,-1是一种更常见的方式来表示它因为'整数'的签名性质。 1真的不能正确,为什么?因为它的非操作是1111 1110.这对于布尔值来说是一个非常重要的问题。当我们谈论一个布尔值时,它只是1位 - 它非常简单,0是假,1是真。所有逻辑操作都是微不足道的。这就是为什么'-1'应该被指定为整数(有符号)的'true'。 1111 1111 NOT'ed变为0000 0000 ---逻辑成立,我们很好。无符号整数有点棘手,并且在过去常用得多 - 其中1表示正确,因为很容易暗示'任何不是0都是真的'的逻辑。

这就是解释。我说这里接受的答案是错误的 - 在C / C ++定义中没有明确的定义。布尔值是布尔值,您可以将整数视为布尔值,但输出是整数的事实说明实际执行的操作是按位的。

答案 6 :(得分:0)

这是因为printf声明中的关系运算符。

运营商==和运营商!=

由于(0 == 0)成立,因此它会给出值1

然而,(0 != 0)并不成立,因此给出了值0