What is the printf format specifier for bool?
Asked Answered
B

8

699

Since ANSI C99 there is _Bool or bool via stdbool.h. But is there also a printf format specifier for bool?

I mean something like in that pseudo code:

bool x = true;
printf("%B\n", x);

which would print:

true
Bakker answered 25/6, 2013 at 20:50 Comment(5)
You can read this for further information cplusplus.com/reference/cstdio/printf You can always make it though!Ultimo
possible duplicate of Best way to print the result of a bool as 'false' or 'true' in c?Papyraceous
@billinkc, my question is not really about what the best way is to print bool values - it is about a concrete printf specifier. Which does not seem to exist. Another angle to a nice answer would be: perhaps there is a way to add a custom format specifier to printf that does the bool conversion ...Bakker
Fair enough, although I don't seem to have the ability to uncast the VtC so I'll just have to wait for my vote to expire.Papyraceous
@maxschlepzig: the only way to solve the problem is to check documentation. If you use GNU/Linux(as example, since you did not tell us about your system), you can read an up-to-date printf manual on [Linux man pages](man7.org). If you want get "true"/"false" strings printed, you can construct them manually, it is pretty easy.Renayrenckens
S
1073

There is no format specifier for bool types. However, since any integral type shorter than int is promoted to int when passed down to printf()'s variadic arguments, you can use %d:

bool x = true;
printf("%d\n", x); // prints 1

But why not:

printf("Your boolean variable is: %s", x ? "true" : "false");

instead?

Selfexpression answered 25/6, 2013 at 20:52 Comment(12)
I would +1 this if you get rid of the non-single-string-literal expression as the format string. This kind of usage easily turns into unsafe usage. printf("%s", x ? "true" : "false"); would fix the issue.Committeewoman
For the "why not" part of this answer -- a format specifier for bool would allow the format string to be used as designed: for constructing a string with a mixture of literals and values.Snubnosed
Just as a note, I'd tend toward disputing that printf("%s", x ? "true" : "false"); is better that printf(x ? "true" : "false"); - you are in total control of the format string here so there is no danger that it'll get something like "%d" which would cause problems. The fputs, on the other hand, is a better option.Midsection
In my case,%dgive -1 or 0. And%ldgive MAX_INT.Crosscut
Why is fputs(x ? "true" : "false", stdout); better than printf("%s", x ? "true" : "false"); and the latter better than printf(x ? "true" : "false");?Obligatory
@HelloGoodbye, passing a single char * to printf() is considered bad practice because it's really supposed to be a format string, and an unescaped percent sign might cause your program to blow up (see here for more). Thus, printf("%s", ...) is safer. If you're not doing any actual formatting to begin with, the printf family of functions is overkill and puts() (or fputs() if you need to print to stderr) is preferable because it's more efficient/concise.Ralleigh
@r: How could this be unsafe? It does not contain any format specifier in the format string - no matter what the ternary operator returns, the format string is always a perfectly save pure string literal.Phytoplankton
I did +1 this, but I'm not sure about your comment regarding "prints 1." I have not read the standard, but I seem to recall from other texts reading that false is zero, and true is "non-zero." Based on implementation, it may print 9, 24, or even a negative value, like -1. If I'm correct, you may want to update your comment to say "prints non-zero" so as to further discourage that unfavorable method.Pipit
Why is fputs "even better"? I'm always looking for ways to improve my C. Under what circumstances should I use fputs instead of printf?Panel
Downvoted for the "why not". That's like saying "why not just format everything yourself?". The obvious answer is "because I'm using a formatting print, I expect it to format all my types sensibly".Starkey
@Arc676, for a string without formatting, fputs is faster and simpler than printf (which has to parse the string looking for formatting chars). Using fputs(stdout) rather than just puts() (which defaults to stdout) eliminates the newline that puts() appends to the output.Hydrops
A good compiler should replace printf() by fputs(stdout) whenever possible, so efficiency is the same.Bricole
S
75

There is no format specifier for bool. You can print it using some of the existing specifiers for printing integral types or do something more fancy:

printf("%s", x?"true":"false");
Supereminent answered 25/6, 2013 at 20:52 Comment(2)
@H2CO3 anyways I have suggested a solution printing "true" and "false" as OP requests. I have also slightly changed my wording on the part you mention.Supereminent
@IvayloStrandjev: Yes, there is a bool type in C, just not in the C89 edition -- it's part of the C99 language spec. There's a new keyword _Bool, and if you include <stdbool.h>, then bool is a synonym for _Bool.Sedan
B
42

ANSI C99/C11 don't include an extra printf conversion specifier for bool.

But the GNU C library provides an API for adding custom specifiers.

An example:

#include <stdio.h>
#include <printf.h>
#include <stdbool.h>

static int bool_arginfo(const struct printf_info *info, size_t n,
    int *argtypes, int *size)
{
  if (n) {
    argtypes[0] = PA_INT;
    *size = sizeof(bool);
  }
  return 1;
}
static int bool_printf(FILE *stream, const struct printf_info *info,
    const void *const *args)
{
  bool b =  *(const bool*)(args[0]);
  int r = fputs(b ? "true" : "false", stream);
  return r == EOF ? -1 : (b ? 4 : 5);
}
static int setup_bool_specifier()
{
  int r = register_printf_specifier('B', bool_printf, bool_arginfo);
  return r;
}
int main(int argc, char **argv)
{
  int r = setup_bool_specifier();
  if (r) return 1;
  bool b = argc > 1;
  r = printf("The result is: %B\n", b);
  printf("(written %d characters)\n", r);
  return 0;
}

Since it is a glibc extensions the GCC warns about that custom specifier:

$ gcc -Wall -g    main.c   -o main
main.c: In function ‘main’:
main.c:34:3: warning: unknown conversion type character ‘B’ in format [-Wformat=]
   r = printf("The result is: %B\n", b);
   ^
main.c:34:3: warning: too many arguments for format [-Wformat-extra-args]

Output:

$ ./main
The result is: false
(written 21 characters)
$ ./main 1
The result is: true
(written 20 characters)
Bakker answered 1/3, 2014 at 12:30 Comment(0)
P
15

In the tradition of itoa():

#define btoa(x) ((x)?"true":"false")

bool x = true;
printf("%s\n", btoa(x));
Pentup answered 25/6, 2013 at 21:0 Comment(10)
btoa is "binary string to base 64 string" in non-standard JavaScript (Gecko and WebKit), so you might want to use a different name.Teraterai
@panzi: I'm not sure it's worth the effort for a C programmer to worry about non-standard JavaScript identifiers.Sophey
@KeithThompson I think I confused the questions and somehow thought this was about JavaScript, which makes no sense anyway. It was probably late at night.Teraterai
Or, for the more devious amongst us: "true\0false"[(!x)*5] :-)Midsection
@paxdiablo: Nice! But, you forgot an & :-)Pentup
@paxdiablo: "false\0true"[x*5] is a touch simplerFilterable
@MooingDuck: maybe !!x*5.Pentup
@jxh: Unnecessary. In mosts contexts, including *, bool is promoted to int with the value 1 or 0, so it's safe. As long as x remains a bool anyway. I see your point.Filterable
@MooingDuck @jxh, shouldn't it be !!x*6, now that false is one char longer than true?Estate
@MustafaZengin: Correct!Pentup
P
5

You can't, but you can print 0 or 1

_Bool b = 1;
printf("%d\n", b);

source

Panegyric answered 25/6, 2013 at 20:52 Comment(0)
D
3

To just print 1 or 0 based on the boolean value I just used:

printf("%d\n", !!(42));

Especially useful with Flags:

#define MY_FLAG (1 << 4)
int flags = MY_FLAG;
printf("%d\n", !!(flags & MY_FLAG));
Drupelet answered 9/12, 2016 at 13:26 Comment(2)
Beware that the !! might get optimized awayReverse
@interestedparty333: If MY_FLAG were equal to 1, then !!(flags & MY_FLAG) could get replaced with (flags & MY_FLAG), but a non-broken compiler would not be able to optimize away !! unless it could prove that the operand couldn't have any value other than 0 or 1.Viperous
S
1

If you like C++ better than C, you can try this:

#include <ios>
#include <iostream>

bool b = IsSomethingTrue();
std::cout << std::boolalpha << b;
Supersensible answered 19/1, 2016 at 19:48 Comment(5)
This answer is off-topic and should be deleted, since it is about another language than the one in the question.Fenrir
@Fenrir I disagree that this should be deleted. The goal of SO isn't just to help one person, but to help all people with the same question. When I search for sprintf print boolean as true false c++, this is the first page that comes up (although arguably this page may have been the top result if this answer didn't exist). Since C++ is nearly a superset of C, I don't think such answers should be so easily discarded. +1 from me.Unshaped
@JeffG Yes such answers should be deleted, we have very clear policies. Read the C and C++ tag wikis. This question isn't helpful to C programmers particularly because the C and C++ boolean systems are entirely different and the question is tagged C. That Google isn't able to understand the two trailing ++ in your search isn't SO's problem.Fenrir
@Fenrir My comment wasn't intended to be interpreted as a comment on SO's policies. It was really a comment about whether this answer adds constructively to the question. This answer is immediately identifiable as C++-only. Nobody coming here for a C-only answer would be tricked into thinking this would work in C and waste time trying it. However, this is a great answer for C++. If answers are useful, even if they don't help the OP, then shouldn't they be kept? I think constructive answers that have clearly identified caveats should never be deleted, regardless of policy.Unshaped
@JeffG You can bring it up on meta.stackoverflow.com, this is not the place to have this discussion.Fenrir
B
-1

I prefer an answer from Best way to print the result of a bool as 'false' or 'true' in c?, just like

printf("%s\n", "false\0true"+6*x);
  • x == 0, "false\0true"+ 0" it means "false";
  • x == 1, "false\0true"+ 6" it means "true";
Brakesman answered 9/1, 2015 at 10:56 Comment(8)
This is totally incomprehensible. It took me a good while before I figured out what "false\0true"+6*x really did. If you work in a project with other people, or just in a project whit a codebase you want to understand x years later, constructions like this is to be avoided.Obligatory
Although I see that this might be more optimized since it is branch-less. If speed is your concern, this might be an option, just make sure to explain the mechanics behind the trick well in a comment. An inline function or macro with a self-documenting name would also be helpful (but probably not sufficient in this case).Obligatory
As well as the concerns about readability bear in mind that this will blow up if someone passes in a value other than 0 or 1.Teran
@Teran You could of course change it to printf("%s\n","false\0true"+6*(x?1:0)); which is only... 5% less readable.Woods
static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; } Same as with static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; just wrap it in a descriptively named function and don't worry about it's readability.Elnoraelnore
Premature optimization. All modern compilers on x86-64 or ARM64 will compile puts( tf ? "true" : "false" ); as a conditional-move instruction, not a branch. On architectures where it would be more efficient, they can generally replace that with something like (char*)((uintptr_t)option1^ (((uintptr_t)x-1U)&((uintptr_t)option1^(uintptr_t)option2))) on targets where that's more efficient. That code is a maintenance nightmare.Morey
Another problem with this solution is that if it is used in foreign languages the number 6 would have to be changed. For example, if x is true "ложь\0истина" + 6*x would print "ь" the last letter in the Russian word for false, because in UTF-8 encoding that word occupies 8 bytes rather than 5. The number 6 would have to be changed to 9.Oshinski
@AlexShroyer what about "false\0true"+6 *!!a ... ;) FWIW, a godbolt link that illustrates @Davislor's point.Bakker

© 2022 - 2024 — McMap. All rights reserved.