Is C/C++ bool type always guaranteed to be 0 or 1 when typecast'ed to int?

43,523

Solution 1

Yes:

In C++ (§4.5/4):

An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.

In C, when a value is converted to _Bool, it becomes 0 or 1 (§6.3.1.2/1):

When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.

When converting to int, it's pretty straight-forward. int can hold 0 and 1, so there's no change in value (§6.3.1.3).

Solution 2

Well, not always...

const int n = 100;
bool b[n];
for (int i = 0; i < n; ++i)
{
    int x = b[i];
    if (x & ~1)
    {
        std::cout << x << ' ';
    }
}

Output on my system:

28 255 34 148 92 192 119 46 165 192 119 232 26 195 119 44 255 34 96 157 192 119
8 47 78 192 119 41 78 192 119 8 250 64 2 194 205 146 124 192 73 64 4 255 34 56 2
55 34 224 255 34 148 92 192 119 80 40 190 119 255 255 255 255 41 78 192 119 66 7
8 192 119 192 73 64 240 255 34 25 74 64 192 73 64

The reason for this apparently weird output is laid out in the standard, 3.9.1 §6:

Values of type bool are either true or false. Using a bool value in ways described by this International Standard as "undefined", such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false.

Solution 3

Is C/C++ .......

There's no language named C/C++.

bool type always guaranteed to be 0 or 1 when typecast'ed to int?

In C++ yes because section $4.5/4 says

An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.

.

int c = 3 + b; // 4 or 5?

The value of c will be 4

Solution 4

One more example when you are out of the safe boat:

  bool b = false;
  *(reinterpret_cast<char*>(&b)) = 0xFF;
  int from_bool = b;
  cout << from_bool << " is " << (b ? "true" : "false");

Output (g++ (GCC) 4.4.7):

  255 is true

To be added to the FredOverflow's example.

Solution 5

There is no bool type in C pre C99 (Such as C90), however the bool type in C99/C++ is always guaranteed to be 0 or 1.

In C, all boolean operation are guaranteed to return either 0 or 1, whether the bool type is defined or not.

So a && b or !a or a || b will always return 0 or 1 in C or C++ regardless of the type of a and b.

Share:
43,523

Related videos on Youtube

mojuba
Author by

mojuba

Passed the Turing Test.

Updated on July 09, 2022

Comments

  • mojuba
    mojuba almost 2 years

    Many compilers seem to be keeping only 0 or 1 in bool values, but I'm not sure this will always work:

    int a = 2;
    bool b = a;
    int c = 3 + b; // 4 or 5?
    
    • Matthew Flaschen
      Matthew Flaschen over 13 years
      For the C++ part, see [Can I assume (bool)true == (int)1 for any C++ compiler ? ](stackoverflow.com/questions/2725044/…). For C, see [Is bool a native C type? ](stackoverflow.com/questions/1608318/is-bool-a-native-c-typ‌​e).
    • bobobobo
      bobobobo about 12 years
      I'm more interested in the question worded as "Is a boolean expression always guaranteed to evaluate to 0 or 1?", to which the answer is unambiguously yes
    • Palec
      Palec over 9 years
    • gnasher729
      gnasher729 about 8 years
      In newer C version, there is a standard bool type which has values 0 and 1 only, as in C++. Assignment converts non-zero to 1.
    • SOFe
      SOFe almost 6 years
      Note that bool cast will make sure b is 1. But you can still make b into 2 using hacks like unions, memset, etc.
  • hhafez
    hhafez over 13 years
    except in C, C doesn't even have a bool type :)
  • Matthew Flaschen
    Matthew Flaschen over 13 years
    C does have bool. Technically, the type is _Bool, and bool is a macro, but that usually doesn't matter unless you're using a conflicting library.
  • Prasoon Saurav
    Prasoon Saurav over 13 years
    @hhafez : In C, until C99, there was no bool datatype. Kindly lift your downvote.
  • eq-
    eq- over 13 years
    @hhafez: Standardized boolean type (_Bool) in C is older than languages like C#. Not too much experience with C, after all?
  • hhafez
    hhafez over 13 years
    what does C have to do with C# I don't understand your comment
  • pmg
    pmg over 13 years
    C99 defined a new type _Bool and a typedef bool in the header <stdbool.h>. If you do not #include <stdbool.h>, your programs cannot use bool, but they can use _Bool.
  • CiscoIPPhone
    CiscoIPPhone over 13 years
    @Sebastian: So uninitialized variables have defined behaviour?
  • fredoverflow
    fredoverflow over 13 years
    @hha: Note the line int x = b[i], I really expected this random stuff to be converted to either 0 or 1 here. Didn't you?
  • hhafez
    hhafez over 13 years
    no not really, the array is just a chunk of uninited memory it can have anything in it, if you had done bool b[n] = {0} then that's a different story. However your quote from the standard is informative so + 1 for pointing out the exception
  • eq-
    eq- over 13 years
    @Sebastian: Trying to access an uninitialized variable is UB. @FredOverflow: Did you? I didn't expect anything, it's UB after all. Do you really think there should be a conversion step each time a boolean value is accessed? There is no defined way to store anything but true or false to a boolean variable.
  • visitor
    visitor over 13 years
    The standard should mention somewhere that an uninitialized bool isn't necessarily either true or false. It can be in some unspecified state.
  • Fabio Fracassi
    Fabio Fracassi over 13 years
    @visitor: The standard says that any uninitialized memory location is in some unspecified state, so yes it does mention it somewhere
  • Jens Gustedt
    Jens Gustedt over 13 years
    @visitor: in the case of C99 and the type _Bool the standard does as far as I remember. _Bool is an unsigned integer type and since it is represented in at least 8 bit, at least 7 of the bits are padding bits. "Values" of the variable that have other bits set may be so-called trap representations and accessing them leads to UB.
  • Sebastian
    Sebastian over 13 years
    @CiscoIPPhone I consider "undefined behavior" to be a technical term that means "the compiler can do whatever it wants with this statement and your program may terminate or not". In this sense, accessing uninitialized memory is clearly defined behavior. You can read it, and the data you read is random. Nothing else is allowed to happen.
  • R.. GitHub STOP HELPING ICE
    R.. GitHub STOP HELPING ICE over 13 years
    @Sebastian: You are simply wrong. Other things, including terminating the program or system("rm -rf /"); are allowed to happen if you access the value of uninitialized variables.
  • Sebastian
    Sebastian over 13 years
  • bobobobo
    bobobobo about 12 years
    @FredOverflow you are pointing out an interesting example that does answer the question - really the value of allocated but not written to memory is going to be some random bytes. Your point is good given the way the question was worded. Argument because the question really should be "Is a boolean expression always guaranteed to evaluate to 0 or 1?"
  • Chris Dodd
    Chris Dodd about 11 years
    Note that for C, it depends on the type _Bool. If you instead have typedef enum { false, true } bool; it does not work this way.
  • thb
    thb over 9 years
    -1 for pointing out that there is no language called C/C++. The remark is pedantically correct, but deliberately unhelpful. It is not as though the original poster had referred to, say, C/SQL. If you know the C++ but not the C standard, just say so.
  • gnasher729
    gnasher729 about 8 years
    Undefined behaviour. No guarantees of the C++ or C standard apply with undefined behaviour.
  • Buster
    Buster over 7 years
    The passage misquoted in this answer doesn't define any undefined behaviour (it simply talks about undefined behaviour, as defined elsewhere in the standard) and doesn't have any bearing on the question. It says nothing at all about values other than "true" and "false" invoking undefined behaviour; quite the reverse. The accurate quote is: "Using a bool value in ways described by this International Standard as “undefined,” such as by examining the value of an uninitialized automatic object, might cause it to behave as if it is neither true nor false."
  • John Bollinger
    John Bollinger over 5 years
    I concur that the representation of _Bool is required to have padding bits, but I'm not seeing a basis for the assertion that "Any bit pattern other than all-bits-zero which could not have been produced by storing a 0 or 1 to a _Bool is a trap representation". It is explicitly possible that _Bool or any other integer type with padding bits affords trap representations, but the standard does not require that or any other particular interpretation of the padding, nor does it require that there be a unique valid representation for every value supported by a given type.
  • supercat
    supercat over 5 years
    @JohnBollinger: The Standard imposes no requirements with regard to how implementations process any bit patterns for which they would not be required to assign a meaning. Implementations may document how they will process reads of such patterns, but they can also document any other action which, from the point of view of the Standard, invokes Undefined Behavior.
  • John Bollinger
    John Bollinger over 5 years
    That is more or less my point, @supercat. The fact that the standard (indirectly) requires the representation of type _Bool to have padding bits does not imply that that type must afford any trap representations, nor are any specific bit patterns meeting the criteria you present required to be trap representations. The standard does not limit valid representations to those that can be stored as a side effect of an assignment expression.
  • supercat
    supercat over 5 years
    @JohnBollinger: From the point of view of the Standard, what is a trap representation if not "an object representation that need not represent a value of the object type", i.e. a bit pattern to which implementations are not required to attach a meaning? Implementations are allowed to attach meanings to bit patterns beyond those required by the Standard, but the fact that an implementation happens to document the meaning of a bit pattern would not prevent it from being an "object representation that need not specify a value of the object type".
  • John Bollinger
    John Bollinger over 5 years
    You are interpreting the definition of trap representation more broadly than I think is intended or warranted. Consider the standard's provision that for sign-value integers, it is implementation-defined whether the representation having sign bit 1 and all other bits 0 is a trap representation. As far as the standard is concerned, that pattern need not represent a value, but it also is not necessarily a trap representation. The "need not represent a value" wording is a bit wrought, I think, but it should be interpreted from the perspective of the implementation.
  • John Bollinger
    John Bollinger over 5 years
    To go at the overall issue from the other direction, however, the standard allows assigning values different from 0 and 1 to objects of type _Bool. It requires the resulting _Bool value to compare equal to either 0 or 1, but it does not limit resulting representations to those arising from assigning 0 or 1, nor does it even require the representation arising from assigning 0 to be all-bits-zero. Your claim, then, seems not to be supported by the standard under even your own interpretation of "trap representation".
  • supercat
    supercat over 5 years
    @JohnBollinger: The Standard requires that all-bits-zero be a valid representation of zero for all integer types, and I don't think _Bool is exempt from that. You are correct that an implementation could decide to use a bit pattern for storing "2" that it would never use when storing "1", provided that reading the object would yield "1" in any case.
  • supercat
    supercat over 5 years
    @JohnBollinger: Do you think the above edit is better?
  • John Bollinger
    John Bollinger over 5 years
    Yes, all-bits-zero is definitely a representation of zero. But it doesn't have to be the only representation of zero, and if there is more than one then all-bits-zero doesn't have to be the representation produced when the value zero is assigned to a _Bool. As for the edit, I do like the new text better. I think it's still too restrictive, but there's more room for interpretation there.
  • supercat
    supercat over 5 years
    @JohnBollinger: I did expressly note that the bit pattern resulting from storing zero need not be all bits zero, and regarded all bits zero as distinct from the bit patterns produced by storing zero or non-zero values.
  • John Bollinger
    John Bollinger over 5 years
    Acknowledged, and again, I do like the updated text better. Thank you.
  • martinkunev
    martinkunev over 4 years
    @thb I disagree that the remark is unhelpful. The idea that C++ is C with more features is quite widespread. The standards of the two languages differ in many ways and this is an important consideration.