C标准是否明确指出真值为0或1?
我们知道任何不等于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
?
C标准是否明确地将真假的真值分别表示为
0
和1
?
C标准在stdbool.h
定义了true
和false
作为macros,分别扩展到1
和0
。
C11-§7.18:
其余的三个macros适用于
#if
预处理指令。 他们是true
其展开为整数常数
1
,false
扩展到整数常数
0
[…]
关于运算符==
和!=
C11-§6.5.9/ 3:
==
(等于)和!=
(不等于)运算符类似于关系运算符,但它们的优先级较低。 108)如果指定的关系为真,则每个运算符产生1
如果为假,则每个运算符产生0
。 结果有int
types。 对于任何一对操作数,其中的一个关系是正确的。
在C11中没有明确指出。 所有语言级别的操作都将返回1,并且接受任何非零值,包括NaN为真。
- 如果你关心
_Bool
,那么true必须是1,因为标准只要求它保持0和1.(§6.2.5/ 2)。 - 同样在
<stdbool.h>
,macrostrue
扩展为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)
但是,所有标准库函数 (例如,第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
types的对象足够大以存储值0和1。§6.5.5.3/ 5 :逻辑否定运算符的结果
!
如果其操作数的值不等于0,则其值为0,如果其操作数的值等于0,则为1。§6.5.8/ 6 :如果指定的关系是
<
(小于),>
(大于),<=
(小于或等于)和>=
(大于或等于)是真的,如果是假的,则为0。 107)…§6.5.9/ 3 :
==
(等于)和!=
(不等于)运算符与关系运算符类似,只是它们的优先级较低.108)如果指定的关系为真,则每个运算符产生1;如果它是假的,则为0。 …§6.5.13/ 3 :如果两个操作数不等于0,
&&
操作符应该产生1; …§6.5.14/ 3 :
||
如果其任一操作数比较不等于0,则运算符应产生1; …§6.10.1/ 1 :…它可以包含一个表单
defined identifier
或defined identifier
一元运算符expression式,如果…§7.4.1(字符分类函数)/ 1 :本小节中的函数返回非零(真),当且仅当…
§7.18/ 3 :其余的三个macros适用于
#if
预处理指令。 它们是 –true
– 扩展到整数常量1,…§7.17.5.1/ 3 :当且仅当对象的操作是无锁的,
atomic_is_lock_free
generics函数返回非零(真)。 …§7.30.2.1(宽字符分类函数)/ 1 :本小节中的函数返回非零(真),当且仅当…
§7.30.2.2.1/ 4 :
iswctype
函数返回非零(true)当且仅当…
当在C中处理布尔值(我指的是true / false值而不是特定的C bool/_Bool
types)时需要注意标准的两个方面。
第一个与expression式的结果有关,可以在C11 6.5 Expressions
(例如关系和相等运算符)的各个部分find。 底线是,只要expression式生成一个布尔值,它…
…如果指定的关系为真,则返回1,否则返回0。 结果有inttypes。
所以,是的,任何布尔生成expression式的结果将是一个为真,或为零为零。 这与您在stdbool.h
中find的内容相匹配,其中标准macrostrue
和false
的定义方式相同。
但请记住,遵循“你所发的是保守的,你所接受的是自由的”的稳健性原则,对布尔环境中的整数的解释是比较宽松的。
再次,从6.5
各个部分,你会看到像这样的语言:
||
如果其任一操作数比较不等于0,则运算符应产生1 ; 否则,结果为0 ,结果为int型。
从那个(和其他部分),很明显,零被认为是错误的, 任何其他的值是真实的。
另外,规定用于布尔生成和解释的值的语言也出现在C99和C89中,所以它们已经存在了相当长的一段时间。 即使是K&R(ANSI-C第二版和第一版)也指定了文本片段,例如:
关系expression式如
i > j
和由&&
和||
连接的逻辑expression式 被定义为具有值1
如果为真,则为0
。在
if
,while
,for
等的testing部分中,“true”意味着“非零”。
&&
运算符…如果两个操作数都不等于零,则返回1,否则返回0。
||
如果操作数比较不等于零,则返回1;否则返回0。
stdbool.h
的macros也会出现在C99中,但是不会出现在C89或K&R中,因为该头文件在该点不存在。
你混合了很多不同的东西:控制语句,运算符和布尔types。 每个人都有自己的规则。
控制语句就像例如if
语句,C11 6.4.8.1:
在这两种forms中,如果expression式不等于0,则执行第一个子语句。
while
for
等有相同的规则。 这与“真”或“假”无关。
对于假定产生布尔结果的运算符,实际上它们产生的值为1或0。例如,相等运算符C11 6.5.9:
如果指定的关系为真,则每个运算符产生1,如果为假,则产生0
所有这些都是因为C直到1999年才有布尔型,即使得到了一个,上面的规则也没有改变。 因此,与大多数语言和运算符产生布尔types(比如C ++和Java)的大多数其他编程语言不同,它们只是产生一个int
值,其值为零或不为零。 例如, sizeof(1==1)
将在C中给出4,而在C ++中为1。
C中的实际布尔types被命名为_Bool
并且需要一个现代编译器。 头文件stdbool.h
定义了macrosbool
, true
和false
,分别扩展为_Bool
, 1
和0
(与C ++兼容)。
然而,将控制语句和操作符看作是实际需要/产生布尔types的编程习惯是很好的。 某些编码标准如MISRA-C推荐了这样的实践。 那是:
if(ptr == NULL)
而不是if(ptr)
。
if((data & mask) != 0)
而不是if(data & mask)
。
这种风格的目的是通过静态分析工具来增加types安全性,从而减less错误。 可以说,这种风格只有在使用静态分析仪时才有意义。 尽pipe在某些情况下会导致更具可读性的自我logging代码
if(c == '\0')
好,意图很清楚,代码是自我logging的。
与
if(c)
坏。 可能意味着什么,我们必须去寻找types的c
来理解代码。 它是一个整数,一个指针还是一个字符?
我用很多语言编程。 我已经看到真正的1或-1取决于语言。 真正的1背后的逻辑是有一点是0或1。真正的-1是背后的逻辑! 运营商是一个补充。 它把所有的1改为0,所有的0改为1。 所以,对于一个int,!0 = -1和!( – 1)= 0。这已经让我绊倒了足够的,我不比较东西是==真,而是比较它是!=假。 这样,我的编程风格适用于每种语言。 所以我的答案是不担心,但程序,使您的代码正确的方式。
这个答案需要更仔细一点。
在C ++中的实际定义是,任何不是0被视为true。 为什么这是相关的? 因为C ++并不知道我们如何思考整数是什么 – 我们创造了这个意义,它所拥有的只是shell和规则的意思。 它知道哪些位是通过哪些构成整数。
1作为一个整数松散地表示为比特,例如8位有符号整数作为0000 0001.很多时候,我们在视觉上看到的是一个谎言,-1是一个更常见的方式来表示它,因为签名的性质'整数'。 1真的不能代表真实,为什么? 因为它不是操作1111 1110.这是一个布尔真正的主要问题。 当我们谈论一个布尔值时,它只是1位 – 它非常简单,0是错误的,1是真的。 所有的逻辑操作都是微不足道的。 这就是为什么“-1”应该被指定为“真”的整数(有符号)。 1111 1111 NOT'ed变成0000 0000 – 逻辑成立,我们很好。 无符号整数有点棘手,过去更常用 – 其中1表示为真,因为很容易暗示“任何不为0的逻辑”。
这是解释。 我说这里接受的答案是错误的 – 在C / C ++定义中没有明确的定义。 一个布尔值是一个布尔值,你可以把一个整数当作一个布尔值,但是输出是一个整数,事实上,所做的操作是按位进行的。
这是因为printf
语句中的关系操作符。
运算符==
和运算符!=
由于(0 == 0)
成立,所以给出值1
而(0 != 0)
不成立,所以给出一个值0
。