我们知道任何不等于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标准是否分别明确指出真值和真值1
和0
?
答案 0 :(得分:91)
C标准是否分别明确指出
true
和false
的真值为0
和1
?
C标准将true
和false
定义为stdbool.h
中的宏,分别扩展为1
和0
。
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 / p>§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
中的内容相符,标准宏true
和false
的定义方式相同。
请记住,遵循“你所发送的保守,你所接受的自由”的健全性原则,布尔上下文中对整数的解释稍微放松一些。 / p>
同样,从6.5
的各个部分,你会看到如下语言:
||
运算符如果其操作数比较不等于0,则产生1;否则,它产生0。结果的类型为int。
从那个(和其他部分),很明显零被认为是假的,而任何其他值都是真的。
另外,指定用于布尔生成和解释的值的语言也会出现在C99和C89中,所以它们已经存在了很长时间。甚至K&amp; R(ANSI-C第二版和第一版)也指定了以下文本段:
i > j
之类的关系表达式和&&
以及||
连接的逻辑表达式被定义为如果为true则值为1
,如果为false则为0
。< / p>在
if
,while
,for
等的测试部分中,“true”仅表示“非零”。
&&
运算符...如果两个操作数的比较不等于零,则返回1,否则返回0。
||
运算符...如果其操作数比较不等于零,则返回1,否则返回0。
stdbool.h
中的宏也会出现在C99中,但不会出现在C89或K&amp; R中,因为那时头文件不存在。
答案 3 :(得分:8)
你混合了许多不同的东西:控制语句,运算符和布尔类型。每个人都有自己的规则。
控制语句的作用类似于if
语句,C11 6.4.8.1:
在两种形式中,如果表达式,则执行第一个子语句 比较不等于0。
while
,for
等具有相同的规则。这与&#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
定义了宏bool
,true
和false
,分别扩展为_Bool
,1
和0
(与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
。