bool的printf格式说明符是什么?


457

由于ANSI C99存在_Boolbool通过stdbool.h。但是还有一个printf bool格式说明符吗?

我的意思是伪代码中的内容:

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

它将打印:

true

1
您可以阅读此内容以获取更多信息cplusplus.com/reference/cstdio/printf尽管可以始终做到!
Varvarigos Emmanouil 2013年


3
@billinkc,我的问题不是真正的关于打印bool值的最佳方法,实际上是关于一个具体的printf说明符。似乎不存在。一个不错的答案的另一个角度是:也许有一种方法可以向printf添加自定义格式说明符,以进行布尔转换...
maxschlepzig 2013年

公平地说,尽管我似乎没有取消VtC的能力,所以我只需要等待我的投票结束即可。
billinkc

@maxschlepzig:解决问题的唯一方法是检查文档。如果您使用GNU / Linux(例如,由于您没有告诉我们有关您的系统的信息),则可以阅读[Linux手册页](man7.org)上的最新printf手册。如果要打印“ true” /“ false”字符串,则可以手动构造它们,这很容易。
Bulat M.

Answers:


709

没有bool类型的格式说明符。但是,由于传递给的可变参数时,int会提升为小于的整数类型,因此可以使用:intprintf()%d

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

但是为什么不呢?

printf(x ? "true" : "false");

或更好:

printf("%s", x ? "true" : "false");

或者,甚至更好:

fputs(x ? "true" : "false", stdout);

代替?


21
如果您将非单字符串文字表达式作为格式字符串删除,我将对此+1。这种用法很容易变成不安全的用法。printf("%s", x ? "true" : "false");将解决此问题。
R .. GitHub停止帮助ICE

2
对于此答案的“为什么不”部分-bool的格式说明符将允许格式字符串按设计使用:用于构造包含文字和值的混合字符串。
noamtm 2014年

13
正如一个音符,我会向争议,往往printf("%s", x ? "true" : "false");更好的是printf(x ? "true" : "false");-你是在的格式字符串这里的控制,有没有危险,它会得到像"%d"这会造成问题。的fputs,在另一方面,一个更好的选择。
paxdiablo 2014年

15
为什么会fputs“更好”?我一直在寻找提高我的C值的方法。在什么情况下应该fputs代替使用printf
Arc676

10
@ Arc676,对于没有格式的字符串,fputs比printf更快(更简单),后者必须解析字符串以查找格式字符。使用fputs(stdout)而不是puts()(默认为stdout)可以消除puts()追加到输出的换行符。
乍得

45

没有用于bool的格式说明符。您可以使用一些现有的用于打印整数类型的说明符来打印它,或者做一些更有趣的事情:

 printf("%s", x?"true":"false");

不需要强制转换。

无论如何,@ H2CO3我建议一个解决方案在OP请求中打印“ true”和“ false”。在您提到的部分,我的措词也略有改变。
Ivaylo Strandjev

5
@IvayloStrandjev:是的,一个bool在C型,只是在没有C89版-它的一部分C99语言规范的。有一个新关键字_Bool,如果包含<stdbool.h>,则bool是的同义词_Bool
亚当·罗森菲尔德2013年

30

ANSI C99 / C11不包含额外的printf转换说明符bool

但是GNU C库提供了用于添加自定义说明符的API

一个例子:

#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;
}

由于它是glibc扩展,因此GCC警告该自定义说明符:

$ gcc -Wall -g main.c -o main
main.c:在函数“ main”中:
main.c:34:3:警告:格式为[-Wformat =]的未知转换类型字符'B'
   r = printf(“结果为:%B \ n”,b);
   ^
main.c:34:3:警告:格式[-Wformat-extra-args]的参数过多

输出:

$ ./main
结果是:false
(写21个字符)
$ ./main 1
结果是:true
(写20个字符)

12

按照以下传统itoa()

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

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

5
btoa在非标准JavaScript(Gecko和WebKit)中是“二进制字符串到64位基本字符串”,因此您可能要使用其他名称。
panzi

26
@panzi:我不确定C程序员担心非标准的JavaScript标识符是否值得付出努力。
基思·汤普森

5
@KeithThompson我认为我很困惑这些问题,并且以某种方式认为这与JavaScript有关,无论如何这是没有意义的。可能是深夜。
panzi 2014年

9
或者,对于我们中间更狡猾的人:"true\0false"[(!x)*5]:-)
paxdiablo

1
@MooingDuck:也许!!x*5
jxh 2015年


2

如果您比C更喜欢C ++,则可以尝试以下方法:

#include <ios>
#include <iostream>

bool b = IsSomethingTrue();
std::cout << std::boolalpha << b;

5
该答案是题外话,应删除,因为它与问题中使用的语言有关。
隆丁'18

2
@Lundin我不同意应将其删除。SO的目标不仅是帮助一个人,而且还帮助所有有相同问题的人。当我将sprintf print布尔值搜索为true false c ++时,这是第一个出现的页面(尽管可以说,如果不存在此答案,则该页面可能是顶部结果)。由于C ++几乎是C的超集,因此我认为不应轻易丢弃此类答案。向我+1。
Jeff G

1
@JeffG是的,应该删除此类答案,我们有非常明确的政策。阅读C和C ++标签Wiki。这个问题对C程序员没有帮助,特别是因为C和C ++布尔系统完全不同,并且该问题标记为C。Google无法理解搜索中的两个尾随++并不是SO的问题。
隆丁

2
@Lundin我的评论并非旨在解释为对SO政策的评论。关于这个答案是否对问题有建设性的补充,确实是一种评论。此答案可立即识别为仅C ++。没有人会来这里寻求仅C语言的答案,不会被认为会在C语言中起作用并且浪费时间进行尝试。但是,这对于C ++是一个很好的答案。如果答案是有用的,即使它们对操作员没有帮助,那么是否不应该保留它们呢?我认为无论政策如何,都不应删除已经明确指出警告的建设性答案。
杰夫G

1
@JeffG您可以在meta.stackoverflow.com上进行讨论,这里不是进行讨论的地方。
隆丁

2

根据我刚刚使用的布尔值仅打印1或0:

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

对于标志尤其有用:

#define MY_FLAG (1 << 4)
int flags = MY_FLAG;
printf("%d\n", !!(flags & MY_FLAG));

当心!!可能会被优化掉
ragerdl

1

我更喜欢“ 最佳方式”的答案,在c语言中将布尔结果打印为“假”或“真”?, 就像

printf("%s\n", "false\0true"+6*x);
  • x == 0,“ false \ 0true” + 0“表示” false“;
  • x == 1,“ false \ 0true” + 6”表示“ true”;

21
这是完全无法理解的。我花了好一会儿才知道"false\0true"+6*x真正的结果。如果您与其他人一起在一个项目中工作,或者只是在想了解x年的代码库的项目中工作,则应避免这样的构造。
HelloGoodbye 2015年

3
尽管我看到它可能更优化,因为它是无分支的。如果您关心速度,则可以选择这种方式,只需确保在评论中很好地解释了窍门的机理。具有自记录名称的内联函数或宏也将有所帮助(但在这种情况下可能还不够)。
HelloGoodbye

3
除了对可读性的担忧外,请记住,如果有人输入0或1以外的值,这将会爆炸。
plugwash 2015年

2
@plugwash当然,您可以将其更改printf("%s\n","false\0true"+6*(x?1:0));为仅...可读性降低5%。
hoosierEE

static inline char const *bool2str(_Bool b) { return "false\0true"+6*x; } int main(void) { printf("%s != %s", bool2str(false), bool2str(true)); return 0; } 与相同static inline char decimal2char(int d) { assert(d >= 0 && d <= 9); return '0' + d; }; 只需将其包装在一个描述性命名的函数中,不必担心它的可读性。
yyny
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.