I have a small piece of code about the sizeof
operator with the ternary operator:
#include
#include
int main()
{
Regarding the boolean type in C
A boolean type was introduced fairly late in the C language, in the year 1999. Before then, C did not have a boolean type but instead used int
for all boolean expressions. Therefore all logical operators such as > == !
etc return an int
of value 1
or 0
.
It was custom for applications to use home-made types such as typedef enum { FALSE, TRUE } BOOL;
, which also boils down to int
-sized types.
C++ had a much better, and explicit boolean type, bool
, which was no larger than 1 byte. While the boolean types or expressions in C would end up as 4 bytes in the worst case. Some manner of compatibility with C++ was introduced in C with the C99 standard. C then got a boolean type _Bool
and also the header stdbool.h
.
stdbool.h
provides some compatibility with C++. This header defines the macro bool
(same spelling as C++ keyword) that expands to _Bool
, a type which is a small integer type, likely 1 byte large. Similarly, the header provides two macros true
and false
, same spelling as C++ keywords, but with backward compatibility to older C programs. Therefore true
and false
expand to 1
and 0
in C and their type is int
. These macros are not actually of the boolean type like the corresponding C++ keywords would be.
Similarly, for backward compatibility purposes, logical operators in C still return an int
to this day, even though C nowadays got a boolean type. While in C++, logical operators return a bool
. Thus an expression such as sizeof(a == b)
will give the size of an int
in C, but the size of a bool
in C++.
Regarding the conditional operator ?:
The conditional operator ?:
is a weird operator with a couple of quirks. It is a common mistake to believe that it is 100% equivalent to if() { } else {}
. Not quite.
There is a sequence point between the evaluation of the 1st and the 2nd or 3rd operand. The ?:
operator is guaranteed to only evaluate either the 2nd or the 3rd operand, so it can't execute any side-effects of the operand that is not evaluated. Code like true? func1() : func2()
will not execute func2()
. So far, so good.
However, there is a special rule stating that the 2nd and 3rd operand must get implicitly type promoted and balanced against each other with the usual arithmetic conversions. (Implicit type promotion rules in C explained here). This means that the 2nd or 3rd operand will always be at least as large as an int
.
So it doesn't matter that true
and false
happen to be of type int
in C because the expression would always give at least the size of an int
no matter.
Even if you would rewrite the expression to sizeof(a ? (bool)true : (bool)false)
it would still return the size of an int
!
This is because of implicit type promotion through the usual arithmetic conversions.