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

max*_*zig 413 c c++ printf boolean

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

我的意思是伪代码:

bool x = true;
printf("%B\n", x);
Run Code Online (Sandbox Code Playgroud)

哪个会打印:

true
Run Code Online (Sandbox Code Playgroud)

小智 633

没有.但是,由于任何整数类型比传递给s变量参数时int提升的更短,您可以使用:intprintf()%d

bool x = true;
printf("%d\n", x); // prints 1
Run Code Online (Sandbox Code Playgroud)

但为什么不呢

printf(x ? "true" : "false");
Run Code Online (Sandbox Code Playgroud)

或更好

printf("%s", x ? "true" : "false");
Run Code Online (Sandbox Code Playgroud)

甚至更好

fputs(x ? "true" : "false", stdout);
Run Code Online (Sandbox Code Playgroud)

代替?

  • 如果您将非单字符串文字表达式作为格式字符串删除,我会+1.这种用法很容易变成不安全的用法.`printf("%s",x?"true":"false");`会解决问题. (16认同)
  • 为什么`fputs`"更好"?我一直在寻找改善我的C.在什么情况下我应该使用`fputs`而不是`printf`? (13认同)
  • 就像一个注释,我倾向于争论'printf("%s",x?"true":"false");`是_better_表示`printf(x?"true":"false"); - 你在这里对格式字符串进行_total_控制,所以有_no_危险它会得到类似`"%d"的东西,这会引起问题.另一方面,`fputs`是一个更好的选择. (11认同)
  • @ Arc676,对于没有格式化的字符串,fput比printf更快更简单(它必须解析字符串以查找格式化字符).使用fputs(stdout)而不仅仅是puts()(默认为stdout)消除了puts()附加到输出的换行符. (9认同)
  • 对于这个答案的"为什么不"部分 - bool的格式说明符将允许格式字符串按设计使用:用于构造具有文字和值的混合的字符串. (2认同)
  • @HelloGoodbye,将一个`char*`传递给`printf()`被认为是不好的做法,因为它确实应该是一个格式字符串,未转义的百分号可能会导致你的程序爆炸([见这里更多]( http://stackoverflow.com/questions/31290850/why-is-printf-with-a-single-argument-without-conversion-specifiers-deprecated)).因此,`printf("%s",...)`更安全.如果你没有开始任何实际的*格式化*,那么`printf`系列函数是过度的,而`puts()`(或`fputs()`如果你需要打印到`stderr`)是可取的,因为它更有效/简洁. (2认同)
  • @r:这怎么可能不安全?它在格式字符串中不包含任何格式说明符——无论三元运算符返回什么,格式字符串始终是一个完美保存的纯字符串文字。 (2认同)
  • 一个好的编译器应该尽可能用 `fputs(stdout)` 替换 `printf()`,所以效率是一样的。 (2认同)

izo*_*ica 39

bool没有格式说明符.您可以使用一些现有的说明符打印它来打印整体类型或做一些更奇特的事情:

 printf("%s", x?"true":"false");
Run Code Online (Sandbox Code Playgroud)

  • @IvayloStrandjev:是的,C中有*一个`bool`类型,而不是C89版本 - 它是C99语言规范的一部分.有一个新的关键字`_Bool`,如果你包含`<stdbool.h>`,那么`bool`是`_Bool`的同义词. (5认同)

max*_*zig 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;
}
Run Code Online (Sandbox Code Playgroud)

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

$ 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]

输出:

$ ./main
The result is: false
(written 21 characters)
$ ./main 1
The result is: true
(written 20 characters)


jxh*_*jxh 12

在以下传统中itoa():

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

bool x = true;
printf("%s\n", btoa(x));
Run Code Online (Sandbox Code Playgroud)

  • @panzi:我不确定C程序员担心非标准的JavaScript标识符是值得的. (24认同)
  • 或者,对于我们中更狡猾的人:""true\0false"[(!x)*5]`:-) (9认同)
  • `btoa`是非标准JavaScript(Gecko和WebKit)中的"二进制字符串到64字符串",因此您可能希望使用其他名称. (5认同)
  • @KeithThompson我觉得我把这些问题弄糊涂了,不知何故认为这是关于JavaScript的,无论如何都没有意义.可能是深夜. (5认同)

Ste*_*han 5

你不能,但你可以打印 0 或 1

_Bool b = 1;
printf("%d\n", b);
Run Code Online (Sandbox Code Playgroud)

来源