简体   繁体   中英

Using _Generic for printf formatting

I find myself often entering in the wrong formatting type, and not remembering when to do f or Lf or lf , etc. Is there a way to do something like the following with the help of the _Generic keyword?

#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.));

Basically, I want it to print:

10.000000 is of type double

Is there a way to do that?

I suppose one shorthand option would be doing something like:

#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

Format specifiers in printf can't be made parameters by themselves. They need to be part of the format string.

You can do this by making the FORMAT macro the entire format string for one call to printf just to print the value. Then you can have another call for the rest:

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

But, as was stated in the comments, modern compilers are smart enough to detect mismatches between printf format strings and their arguments. So relying on that works just as well.

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

Note that for float and double , l or not l are valid as float augments to a ... parameter are promoted to double . The l is optional with printf specifier "%f" , and friends: fFeEgGaA .

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

To use _Generic for printing, perhaps Formatted print without the need to specify type matching specifiers using _Generic .

A useful reason to use different print specifiers for float/double is precision.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM