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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37291681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:25:46  来源:igfitidea点击:

Does the C standard explicitly indicate truth value as 0 or 1?

c

提问by Kevin Dong

We know that any numbers that are not equal to 0are viewed as truein C, so we can write:

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

int a = 16;

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

However, I was wondering whether true / false are defined as 1/0in C, so I tried the code below:

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

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

Does C standard explicitly indicate the truth values of true and false as 1and 0respectively?

C 标准是否明确表示真假的真值分别为10

回答by haccks

Does the C standard explicitly indicate the truth values of trueand falseas 0and 1respectively?

C 标准是否分别明确指出了truefalseas0和as的真值1

The C standard defines trueand falseas macros in stdbool.hwhich expand to 1and 0respectively.

C 标准将true和定义false为宏,stdbool.h其中分别扩展为10

C11-§7.18:

C11-§7.18:

The remaining three macros are suitable for use in #ifpreprocessing directives. They are

true

which expands to the integer constant 1,

false

which expands to the integer constant 0[...]

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

true

它扩展为整数常量1

false

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

Regarding the operators ==and !=

关于运营商==!=

C11-§6.5.9/3:

C11-§6.5.9/3:

The ==(equal to) and !=(not equal to) operators are analogous to the relational operators except for their lower precedence.108)Each of the operators yields 1if the specified relation is true and 0if it is false. The result has type int. For any pair of operands, exactly one of the relations is true.

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

回答by kennytm

It is not explicitly indicated in C11. All language-level operationswill return 1 as truthy (and accept any nonzero including NaN as true).

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

  • If you concern about _Bool, then true must be 1 because the standard only require it to hold 0 and 1. (§6.2.5/2).
  • Also in <stdbool.h>the macro trueexpands to 1(§7.18/3)
  • ==, !=, <, >, <=and >=return 0 or 1 (§6.5.8/6, §6.5.9/3).
  • !, &&and ||return 0 or 1 (§6.5.3.3/5, §6.5.13/3, §6.5.14/3)
  • definedexpands to 0 or 1 (§6.10.1/1)
  • 如果您担心_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 节)

But all standard library functionse.g. islowerjust say "nonzero" for truthy (e.g. §7.4.1/1, §7.17.5.1/3, §7.30.2.1/1, §7.30.2.2.1/4).

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



§6.2.5/2: An object declared as type _Boolis large enough to store the values 0 and 1.

§6.5.5.3/5: The result of the logical negation operator !is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. …

§6.5.8/6: Each of the operators <(less than), >(greater than), <=(less than or equal to), and >=(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.107) …

§6.5.9/3: The ==(equal to) and !=(not equal to) operators are analogous to the relational operators except for their lower precedence.108) Each of the operators yields 1 if the specified relation is true and 0 if it is false. …

§6.5.13/3: The &&operator shall yield 1 if both of its operands compare unequal to 0; …

§6.5.14/3: The ||operator shall yield 1 if either of its operands compare unequal to 0; …

§6.10.1/1: … it may contain unary operator expressions of the form — defined identifier— or — defined ( identifier )— which evaluate to 1 if …

§7.4.1 (Character classification functions)/1: The functions in this subclause return nonzero (true) if and only if …

§7.18/3: The remaining three macros are suitable for use in #ifpreprocessing directives. They are — true— which expands to the integer constant 1, …

§7.17.5.1/3: The atomic_is_lock_freegeneric function returns nonzero (true) if and only if the object's operations are lock-free. …

§7.30.2.1 (Wide character classification functions)/1: The functions in this subclause return nonzero (true) if and only if …

§7.30.2.2.1/4: The iswctypefunction returns nonzero (true) if and only if …

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

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

§6.5.8/6:如果指定的关系为真,则每个运算符<(小于)、>(大于)、<=(小于或等于)和>=(大于或等于)应产生 1 和 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 )— 的一元运算符表达式,如果 ...

§7.4.1(字符分类函数)/1:当且仅当……本小节中的函数返回非零(真)。

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

§7.17.5.1/3atomic_is_lock_free泛型函数返回非零(真)当且仅当对象的操作是无锁的。…

§7.30.2.1(宽字符分类函数)/1:当且仅当……本小节中的函数返回非零(真)。

§7.30.2.2.1/4iswctype当且仅当......函数返回非零(真)

回答by paxdiablo

There are two areas of the standard you need to be aware with when dealing with Boolean values (by which I mean true/false values rather than the specific C bool/_Booltype) in C.

在 C 中处理布尔值(我指的是真/假值而不是特定的 Cbool/_Bool类型)时,您需要注意标准的两个方面。

The first has to do with the resultof expressions and can be found in various portions of C11 6.5 Expressions(relational and equality operators, for example) . The bottom line is that, whenever a Boolean value is generated by an expression, it ...

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

... yields 1 if the specified relation is true and 0 if it is false. The result has type int.

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

So, yes, the result of any Boolean-generating expression will be one for true, or zero for false. This matches what you will find in stdbool.hwhere the standard macros trueand falseare defined the same way.

所以,是的,任何布尔生成表达式的结果都是 1 表示真,或 0 表示假。这与您将在stdbool.h标准宏中找到的内容相匹配,true并且false以相同的方式定义。

Keep in mind however that, following the robustness principle of "be conservative in what you send, liberal in what you accept", the interpretation of integersin the Boolean context is somewhat more relaxed.

但是请记住,遵循“发送内容保守,接受内容自由”的稳健性原则,布尔上下文中整数的解释稍微宽松一些。

Again, from various parts of 6.5, you'll see language like:

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

The ||operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it yields 0.The result has type int.

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

From that (and other parts), it's obvious that zero is considered false and anyother value is true.

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



As an aside, the language specifying what value are used for Boolean generation and interpretation also appear back in C99 and C89 so they've been around for quite some time. Even K&R (ANSI-C second edition andthe first edition) specified that, with text segments such as:

顺便说一句,指定用于布尔值生成和解释的值的语言也出现在 C99 和 C89 中,因此它们已经存在了很长一段时间。甚至 K&R(ANSI-C 第二版第一版)也指定了这一点,文本段例如:

Relational expressions like i > jand logical expressions connected by &&and ||are defined to have value 1if true, and 0if false.

In the test part of if, while, for, etc, "true" just means "non-zero".

The &&operator ... returns 1 if both its operands compare unequal to zero, 0 otherwise.

The ||operator ... returns 1 if either its operands compare unequal to zero, and 0 otherwise.

关系表达式 likei > j和由&&和连接的逻辑表达式||被定义为具有值,1如果为真,0如果为假。

在、、 等的测试部分中if,“true”仅表示“非零”。whilefor

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

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

The macros in stdbool.happear back in C99 as well, but not in C89 or K&R since that header file did not exist at that point.

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

回答by Lundin

You are mixing up a lot of different things: control statements, operators and boolean types. Each have their own rules.

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

Control statements work like for example the ifstatement, C11 6.4.8.1:

控制语句的工作方式类似于if语句 C11 6.4.8.1:

In both forms, the first substatement is executed if the expression compares unequal to 0.

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

while, foretc have the same rule. This has nothing to do with "true" or "false".

whilefor等有相同的规则。这与“真”或“假”无关。

As for operators that are supposedly yielding a boolean result, they are actually yielding an intwith value 1 or 0. For example the equality operators, C11 6.5.9:

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

Each of the operators yields 1 if the specified relation is true and 0 if it is false

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

All of the above is because C did not have a boolean type until the year 1999, and even when it did get one, the above rules weren't changed. So unlike most other programming languages where statements and operators yield a boolean type (like C++ and Java), they just yield an int, with a value zero or not zero. For example, sizeof(1==1)will give 4 in C but 1 in C++.

以上都是因为 C 直到 1999 年才拥有 boolean 类型,甚至当它得到了一个布尔类型时,上述规则也没有改变。因此,与大多数其他编程语言不同,语句和运算符产生布尔类型(如 C++ 和 Java),它们只产生一个int,其值为零或不为零。例如,sizeof(1==1)将在 C 中给出 4,而在 C++ 中给出 1。

The actual boolean type in C is named _Booland requires a modern compiler. The header stdbool.hdefines macros bool, trueand false, that expand to _Bool, 1and 0respectively (for compatibility with C++).

C 中的实际布尔类型已命名_Bool并需要现代编译器。头文件stdbool.h定义了宏bool,truefalse,分别扩展为_Bool,10(为了与 C++ 兼容)。



It is however considered good programming practice to treat control statements and operators as if they actually required/yielded a boolean type. Certain coding standards like MISRA-C recommend such practice. That is:

然而,将控制语句和运算符视为实际需要/产生布尔类型被认为是良好的编程实践。某些编码标准(如 MISRA-C)推荐这种做法。那是:

if(ptr == NULL)instead of if(ptr).

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

if((data & mask) != 0)instead of if(data & mask).

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

The aim of such style is to increase type safety with the aid of static analysis tools, which in turn reduces bugs. Arguably, this style is only meaningful if you do use static analysers. Though in some cases it leads to more readable, self-documenting code, for example

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

if(c == '
if(c) 
')

Good, the intent is clear, the code is self-documenting.

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

versus

相对

##代码##

Bad. Could mean anything, and we have to go look for the type of cto understand the code. Is it an integer, a pointer or a character?

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

回答by Russell Hankins

I've programmed in many languages. I've seen true be 1 or -1 depending on the language. The logic behind true being 1 was that a bit was either a 0 or 1. The logic behind true being -1 was that the ! operator was a one's complement. It changed all the 1's to 0's and all the 0's to 1's in an int. So, for an int, !0 = -1 and !(-1) = 0. This has tripped me up enough that I don't compare something to be == true, but instead compare it to be != false. That way, my programming style works in every language. So my answer is to not worry about it, but program so that your code works correctly either way.

我用多种语言编程。我已经看到 true 为 1 或 -1,具体取决于语言。true 为 1 背后的逻辑是一个位要么是 0 要么是 1。true 成为 -1 背后的逻辑是 ! 运算符是一个人的补充。它在一个 int 中将所有 1 更改为 0,并将所有 0 更改为 1。所以,对于一个整数,!0 = -1 和 !(-1) = 0。这让我很受挫,我没有将某些东西比较为 == 真,而是将其比较为 != 假。这样,我的编程风格适用于每种语言。所以我的答案是不要担心它,而是要进行编程,以便您的代码以任何一种方式都能正常工作。

回答by Tommy

This answer needs to be looked at a bit more closely.

这个答案需要更仔细地看一下。

The actual definition in C++ is that anything not 0 is treated as true. Why is this relevant? Because C++ doesn't know what an integer is by how we think about it--we create that meaning, all it holds is the shell and rules for what that means. It knows what bits are though, that which make up an integer.

C++ 中的实际定义是任何不为 0 的都被视为真。为什么这是相关的?因为 C++ 不知道我们如何看待整数是什么——我们创造了这个含义,它所拥有的只是外壳和含义的规则。它知道哪些位是组成整数的位。

1 as an integer is loosely represented in bits, say an 8-bit signed int as 0000 0001. Many times what we see visually is a bit of a lie, -1 is a much more common way to represent it because of the signed nature of 'integer'. 1 really can't mean true proper, why? Because it's NOT operation is 1111 1110. That's a really major issue for a boolean. When we talk about a boolean, it's just 1 bit--it's really simple, 0 is false and 1 is true. All the logic operations hold as trivial. This is why '-1' should be designated as 'true' for integers (signed). 1111 1111 NOT'ed becomes 0000 0000---the logic holds and we're good. Unsigned ints is a little bit tricky and were a lot more commonly used in the past--where 1 means true because it's easy to imply the logic that 'anything not 0 is true'.

1 作为整数以位为单位松散地表示,例如 8 位有符号整数为 0000 0001。很多时候我们在视觉上看到的有点撒谎,-1 是一种更常见的表示方式,因为有符号的性质'整数'。1 真的不能代表真正的正确,为什么?因为它不是操作是 1111 1110。这对于布尔值来说是一个真正的主要问题。当我们谈论布尔值时,它只是 1 位——它真的很简单,0 为假,1 为真。所有的逻辑操作都是微不足道的。这就是为什么对于整数(有符号)应该将“-1”指定为“真”的原因。1111 1111 NOT'ed 变为 0000 0000 ---逻辑成立,我们很好。无符号整数有点棘手,过去更常用——其中 1 表示真,因为很容易暗示 '

That's the explanation. I say the accepted answer here is wrong--there is no clear definition in the C/C++ definition. A boolean is a boolean, you can treat an integer as a boolean, but the fact the output is an integer says nothing about the operation actually being done is bitwise.

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

回答by SKD

It happened because of the Relational Operators in your printfstatement.

它的发生是因为您printf语句中的关系运算符。

Operator ==and operator !=

操作员==和操作员!=

Since (0 == 0)holds true so, it gives a value 1

由于(0 == 0)成立的话,它给出的值1

whereas, (0 != 0)doesn't hold true so, gives a value 0.

而,(0 != 0)不成立,所以给出一个 value 0