printf conversion specifier for _Bool?

19,451

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

_Bool

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:

typedef int8_t _Bool;

typedef enum { false = 0, true = 1 } bool;

typedef unsigned char Boolean; typedef _Bool Boolean;

Share:
19,451

Related videos on Youtube

Richard Hansen
Author by

Richard Hansen

Updated on September 15, 2022

Comments

  • Richard Hansen
    Richard Hansen over 1 year

    With printf(), I can use %hhu for unsigned char, %hi for a short int, %zu for a size_t, %tx for a ptrdiff_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
      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
      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's typedefed (right?). Also, 6.3.1.2 describes special conversion rules for _Bool, which won't work if _Bool is simply typedefed to int.
    • Jim Balter
      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
      Keith Thompson almost 12 years
      @Jack: _Bool is definitely not a typedef for int. _Bool is a keyword, and it's a distinct type.
    • Sergey Kalinichenko
      Sergey Kalinichenko
      I don't think you need a cast in front of foo: _Bool will be cast to int by default.
  • Jite
    Jite almost 12 years
    or if you want to print a string as output you could do: printf("foo: %s\n", foo ? "true" : "false");
  • Richard Hansen
    Richard Hansen almost 12 years
    Sure, 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
    ecatmur almost 12 years
    It's impossible to store into _Bool any value other than 0 or 1 (6.3.1.2). So the conversion back to int will (barring undefined behaviour) always yield 0 or 1.
  • Keith Thompson
    Keith Thompson almost 12 years
    @ecatmur: Yes, and the macros false and true in <stdbool.h> expand to 0 and 1, respectively.
  • ouah
    ouah almost 12 years
    C says _Bool is an unsigned integer type so -1 is not possible.
  • Jim Balter
    Jim Balter almost 12 years
    The 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
    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
    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
    tomlogic almost 12 years
    @ecatmur and ouah: thanks for that information, I've updated my answer.
  • Jim Balter
    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
    tomlogic almost 12 years
    And 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 a bool type, and a Boolean type that is defined as an unsigned char or _Bool.
  • Richard Hansen
    Richard Hansen almost 12 years
    C99 6.3.1.1p2 says "If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int." Since an int can represent all values of a _Bool, it will be promoted to an int, not an unsigned int (even though _Bool is an unsigned integer type).
  • Richard Hansen
    Richard Hansen almost 12 years
    This is currently the most correct answer -- _Bool will be promoted to an int, not an unsigned int. For posterity, it'd be nice if the answer contained references to the C99 standard specifying this behavior.
  • Richard Hansen
    Richard Hansen almost 12 years
    6.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