printf conversion specifier for _Bool?
Solution 1
There is no specific conversion length modifier for _Bool
type.
_Bool
is an unsigned integer type large enough to store the values 0
and 1
. You can print a _Bool
this way:
_Bool b = 1;
printf("%d\n", b);
Because of the integer promotions rules, _Bool
is guaranteed to promote to int
.
Solution 2
Until C99, bool was not apart of standard C, and thus did not exist as a printf modifier. C99, defined _Bool (which you are using) to be an integer, thus you should be fine casting it as an integer to display (at least from a machine perspective). Alternatively, you could do something like:
printf("%d",foo?1:0);
Solution 3
As you stated in a comment to @Jack, "6.3.1.1p1 says that the conversion rank of _Bool
is less than the rank of all other standard integer types".
In a call to printf
, a char
or short
will be promoted and passed on the stack as an int
(or an unsigned int
), so I would think that using %d
as a format specifier would be fine. That also means that you don't need the explicit cast to int
, because that will happen automatically.
The only possible issue would be with how the compiler represents a _Bool
, something that it probably implementation defined and could vary from one compiler to another. I see two likely implementations -- 0 and 1 or 0 and -1.
For the ultimate in portability, follow @user325181's answer and use a ternary to choose between two options. Either integers (which the compiler may optimize away) or strings.
Edit: As reported in other answers, a _Bool
is defined as an unsigned integral type that can store either 0 or 1. Because of that, and the fact that it will be promoted to an unsigned
int
when passed to printf()
, I would say that %u
%d
is the most appropriate specifier.
Solution 4
There is no. Just handling it like an int
by using %d
or %i
specifier.
In C99, a new keyword, _Bool, is introduced as the new boolean type. In many aspects, it behaves much like an unsigned int, but conversions from other integer types or pointers always constrained to 0 and 1. Other than for other unsigned types, and as one would expect for a boolean type, such a conversion is 0 if and only if the expression in question evaluates to 0 and it is 1 in all other cases. The header stdbool.h provides macros bool, true and false that are defined as _Bool, 1 and 0, respectively.
The first way to implement it that come from into mind is by using a char
or(int8_t
) an enum
and with bit fields
. But actually, it depends. It can be a typedef
for an int
(as I've mentioned, it's used, but is not recommend, subject to bugs) or char
or unsigned int
or an enum and #define
that's commonly used.
For exampe, Apple's implementation uses int
,as you can see:
#ifndef _STDBOOL_H_
#define _STDBOOL_H_
#define __bool_true_false_are_defined 1
#ifndef __cplusplus
#define false 0
#define true 1
#define bool _Bool
#if __STDC_VERSION__ < 199901L && __GNUC__ < 3
typedef int _Bool;
#endif
#endif /* !__cplusplus */
#endif /* !_STDBOOL_H_ */
Others implementations:
Related videos on Youtube
Richard Hansen
Updated on September 15, 2022Comments
-
Richard Hansen over 1 year
With
printf()
, I can use%hhu
forunsigned char
,%hi
for ashort int
,%zu
for asize_t
,%tx
for aptrdiff_t
, etc.What conversion format specifier do I use for a
_Bool
? Does one exist in the standard?Or do I have to cast it like this:
_Bool foo = 1; printf("foo: %i\n", (int)foo);
-
Sergey Kalinichenko almost 12 years@RichardHansen If I recall it correctly, default promotions always apply to varargs: floats become doubles, chars become ints, and so on. This may have changed in C99, I am not sure.
-
Richard Hansen almost 12 years@Jack: I'm skeptical -- citation needed. :) C99 6.3.1.1p1 says that the conversion rank of
_Bool
is less than the rank of all other standard integer types, which can't be true if it'stypedef
ed (right?). Also, 6.3.1.2 describes special conversion rules for_Bool
, which won't work if_Bool
is simplytypedef
ed toint
. -
Jim Balter almost 12 years@Jack No, it most certainly is not; please don't post false information. The default promotions apply when the type of the parameter isn't declared, so _Bool is implicitly converted to int.
-
Keith Thompson almost 12 years@Jack:
_Bool
is definitely not a typedef forint
._Bool
is a keyword, and it's a distinct type. -
Sergey KalinichenkoI don't think you need a cast in front of
foo
:_Bool
will be cast toint
by default.
-
-
Jite almost 12 yearsor if you want to print a string as output you could do:
printf("foo: %s\n", foo ? "true" : "false");
-
Richard Hansen almost 12 yearsSure, that alternative also works and is probably easier to type. However, I'm less interested in the various ways to print
_Bool
than confirmation that there is no length modifier or conversion specifier for_Bool
. (A bonus would be a link to discussion as to why it doesn't exist: Oversight? Deemed unnecessary?) -
ecatmur almost 12 yearsIt's impossible to store into
_Bool
any value other than0
or1
(6.3.1.2). So the conversion back toint
will (barring undefined behaviour) always yield0
or1
. -
Keith Thompson almost 12 years@ecatmur: Yes, and the macros
false
andtrue
in<stdbool.h>
expand to0
and1
, respectively. -
ouah almost 12 yearsC says
_Bool
is an unsigned integer type so-1
is not possible. -
Jim Balter almost 12 yearsThe responses in the comments above are correct: there is no need to cast it, because it is automatically promoted ... and so there is no need for the ?: either. And the fact that there wasn't a printf modifier before C99 is irrelevant; they could have added one when they added _Bool ... but if they had, it would have printed "true" or "false".
-
Jim Balter almost 12 years@RichardHansen You can determine what printf formats there are and a lot more by obtaining and reading the standard yourself online, as there are free working drafts before and after the official standard ... just google C99 standard.
-
Jim Balter almost 12 years@RichardHansen You can also obtain the C99 Rationale online. However, there is no mention there of a printf format for _Bool (to be expected, as mostly it explains why things were done, rather than why they weren't).
-
tomlogic almost 12 years@ecatmur and ouah: thanks for that information, I've updated my answer.
-
Jim Balter almost 12 years%u works as well, especially for those retentive types like myself who prefer to always use unsigned specifiers with unsigned types. Also, I think
_Bool b = true;
is better usage. -
tomlogic almost 12 yearsAnd none of those implementations are C99.
_Bool
is a keyword in C99, and you won't find it defined in any headers. In the Apple example above, it's defining it for versions of C before C99. In your other examples, you have abool
type, and aBoolean
type that is defined as anunsigned char
or_Bool
. -
Richard Hansen almost 12 yearsC99 6.3.1.1p2 says "If an
int
can represent all values of the original type, the value is converted to anint
; otherwise, it is converted to anunsigned int
." Since anint
can represent all values of a_Bool
, it will be promoted to anint
, not anunsigned int
(even though_Bool
is an unsigned integer type). -
Richard Hansen almost 12 yearsThis is currently the most correct answer --
_Bool
will be promoted to anint
, not anunsigned int
. For posterity, it'd be nice if the answer contained references to the C99 standard specifying this behavior. -
Richard Hansen almost 12 years6.5.2.2p7 for default argument promotions for arguments corresponding to the ellipsis, 6.5.2.2p6 for the definition of default argument promotion, 6.3.1.1 for integer promotions