使用 _Generic 进行 printf 格式化

Using _Generic for printf formatting

我发现自己经常输入错误的格式类型,并且不记得什么时候输入 fLflf 等。有没有办法做类似的事情以下借助 _Generic 关键字?

#define TYPE(X)   _Generic((X), float: "float", double: "double", long double: "long_double")
#define FORMAT(X) _Generic((X), float: "%f",    double: "%f",     long double: "%Lf")

printf("%s if of type %s\n", FORMAT(10.), 10., TYPE(10.));

基本上,我希望它打印:

10.000000 is of type double

有办法吗?

我想一个 shorthand 选项会做这样的事情:

#define TYPE(X)     _Generic((X), float: "float", double: "double", long double: "long_double")
#define STRINGIZE(X)   #X
printf("%s if of type %s\n", STRINGIZE(10.), TYPE(10.));
  1. if of type double

printf中的格式说明符不能自己做参数。它们需要是格式字符串的一部分。

您可以通过使 FORMAT 宏成为一次调用 printf 的整个格式字符串来实现这一点,只是为了打印该值。然后你可以再打电话休息:

printf(FORMAT(10.), 10.);
printf(" is of type %s\n", TYPE(10.));

但是,正如评论中所述,现代编译器足够智能,可以检测 printf 格式字符串与其参数之间的不匹配。因此,依靠它也同样有效。

wrong formatting type, and not remembering when to do f or Lf or lf, etc.

请注意,对于 floatdoublell 都是有效的,因为 float... 参数的扩充是晋升为 doublel 是可选的 printf 说明符 "%f",朋友们:fFeEgGaA.

printf("%f\n", 1.2f);
printf("%f\n", 3.4);
printf("%lf\n", 5.6f); // unusual, yet OK
printf("%lf\n", 7.8);

要使用_Generic进行打印,可能Formatted print without the need to specify type matching specifiers using _Generic

float/double 使用不同的打印说明符的一个有用原因是精度。

#define ForD(X)   _Generic((X), float: FLT_DECIMAL_DIG-1, double: DBL_DECIMAL_DIG-1)
printf("%.*e\n", ForD(f), f);  // Best if `f` is not be an expression.