Does the C standard explicitly indicate truth valu

2020-02-07 19:16发布

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

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/0 in C, so I tried the code below:

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 1 and 0 respectively?

标签: c
7条回答
Ridiculous、
2楼-- · 2020-02-07 19:53

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 if statement, C11 6.4.8.1:

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

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

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

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

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++.

The actual boolean type in C is named _Bool and requires a modern compiler. The header stdbool.h defines macros bool, true and false, that expand to _Bool, 1 and 0 respectively (for compatibility with 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:

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

if((data & mask) != 0) instead of 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 == '\0') 

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

versus

if(c) 

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

查看更多
Viruses.
3楼-- · 2020-02-07 19:54

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.

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'.

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.

查看更多
女痞
4楼-- · 2020-02-07 19:56

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

The C standard defines true and false as macros in stdbool.h which expand to 1 and 0 respectively.

C11-§7.18:

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

true

which expands to the integer constant 1,

false

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

Regarding the operators == and !=

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 1 if the specified relation is true and 0 if it is false. The result has type int. For any pair of operands, exactly one of the relations is true.

查看更多
5楼-- · 2020-02-07 19:56

It happened because of the Relational Operators in your printf statement.

Operator == and operator !=

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

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

查看更多
够拽才男人
6楼-- · 2020-02-07 20:07

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.

查看更多
ら.Afraid
7楼-- · 2020-02-07 20:08

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

  • 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 true expands 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)
  • defined expands to 0 or 1 (§6.10.1/1)

But all standard library functions e.g. islower just 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).


§6.2.5/2: An object declared as type _Bool is 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 #if preprocessing directives. They are — true — which expands to the integer constant 1, …

§7.17.5.1/3: The atomic_is_lock_free generic 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 iswctype function returns nonzero (true) if and only if …

查看更多
登录 后发表回答