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

Kev*_*ong 82 c

我们知道任何不相等的数字0都被视为trueC,所以我们可以写:

int a = 16;

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

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

printf("True = %d, False = %d\n", (0 == 0), (0 != 0));  // prints: True = 1, False = 0
Run Code Online (Sandbox Code Playgroud)

请问C标准明确指示的真正的真值和假的10分别?

hac*_*cks 93

C标准是否明确指出了真值truefalseas 01

C标准定义truefalse作为宏分别stdbool.h扩展到10.

C11-§7.18:

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

true
Run Code Online (Sandbox Code Playgroud)

它扩展为整数常量1,

false
Run Code Online (Sandbox Code Playgroud)

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

关于运营商==!=

C11-§6.5.9/ 3:

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

  • 在我看来,问题是关于"0 == 0"和"0!= 0"等,而不是宏的值. (19认同)
  • 我认为,当他写"真"时,他的意思是"真正比较的价值"或其他东西,而不是宏"真实" (9认同)
  • @MooingDuck:`NaN == NaN`为假,'NaN!= NaN`为真.该声明没有问题. (2认同)

ken*_*ytm 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:声明为type的对象_Bool足以存储值0和1.

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

§6.5.8/ 6:如果指定的关系为真,则每个运算符<(小于),>(大于),<=(小于或等于)和>=(大于或等于)将产生1,如果指定的关系为0则为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 )- 如果......,则评估为1

§7.4.1(字符分类函数)/ 1:当且仅当...时,本子句中的函数返回非零(真)

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

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

§7.30.2.1(宽字符分类函数)/ 1:当且仅当...时,本子句中的函数返回非零(真)

§7.30.2.2.1/ 4:iswctype当且仅当...时,函数返回非零(true)


pax*_*blo 21

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

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

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

所以,是的,任何布尔生成表达式的结果都是一个表示true,或者0表示false.这与stdbool.h标准宏所在的位置匹配,truefalse以相同的方式定义.

但请记住,遵循"你所发送的保守,你接受的自由"的鲁棒性原则,布尔语境中整数的解释稍微放松一些.

再次,从各个部分6.5,你会看到如下语言:

||操作人员应得到1如果任一操作数的比较不等于0; 否则,它产生0.结果类型为int.

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


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

如果为true,则关系表达式i > j和由&&和连接的逻辑表达式||定义为具有值,1如果为true,0则为false.

在测试部分if,while,for,等,"真"只是意味着"非零".

&&运营商...如果两个操作数比较不等于零,否则为0返回1.

||运营商...返回1,如果任一操作数比较不等于零,否则为0.

stdbool.h也会出现在C99中,但不会出现在C89或K&R中,因为该头文件在该点不存在.

  • 请注意`||`,`==`,`!=`等.产生`int`,而不是布尔类型 (2认同)
  • 我把这个问题投给了正确的问题.对我来说,问题还在于关系运​​算符而不是宏. (2认同)

Lun*_*din 9

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

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

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

while,for等有相同的规则.这与"真实"或"虚假"无关.

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

如果指定的关系为真,则每个运算符产生1,如果为假,则产生0

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

C中的实际布尔类型是命名的_Bool,需要现代编译器.头stdbool.h定义的宏bool,truefalse展开后_Bool,10分别(用于C++兼容性).


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

if(ptr == NULL)而不是if(ptr).

if((data & mask) != 0)而不是if(data & mask).

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

if(c == '\0') 
Run Code Online (Sandbox Code Playgroud)

好,意图很清楚,代码是自我记录的.

if(c) 
Run Code Online (Sandbox Code Playgroud)

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