[英]Using macros inside a printf string in C?
Given 3 doubles x, y and z, I make a lot of such printf calls:给定 3 个双打 x、y 和 z,我进行了很多这样的 printf 调用:
printf("[%+-8.3lf, %+-8.3lf, %+-8.3lf]\n", x, y, z);
I then would like to have a macro of some sort to write something like this:然后我想有一个宏来写这样的东西:
#define FORMAT(x,y) "+-x.ylf"
printf("[%FORMAT(8,3), %FORMAT(8,3), %FORMAT(8,3)]\n", a->x, a->y, a->z);
But of course, the compiler sees %F as a special string and doesn't get my macro inside the string.但当然,编译器将 %F 视为特殊字符串,并且不会将我的宏放入字符串中。 Is there a way to achieve what I want?
有没有办法实现我想要的?
FORMAT
FORMAT
Your "something like this" code is close — but you need to use string concatenation (of adjacent string literals) and the #
operator to 'stringize' macro arguments:您的“类似这样”的代码很接近 - 但您需要使用字符串连接(相邻字符串文字)和
#
运算符来“字符串化”宏 arguments:
#define FORMAT(x,y) "%+-" #x "." #y "lf"
printf("[" FORMAT(8,3) ", " FORMAT(8,3) ", " FORMAT(8,3) "]\n",
a->x, a->y, a->z);
This is similar to using the macros from <inttypes.h>
for printing types such as int64_t
, except with those, you have to provide the %
symbol (and any flags):这类似于使用
<inttypes.h>
中的宏来打印类型,例如int64_t
,除了那些,你必须提供%
符号(和任何标志):
uint64_t x = 0x43218765CBA9;
printf("x = 0x%.12" PRIX64 "\n", x);
Would there be a way to define my 8 and 3 values as macros too?
有没有办法将我的 8 和 3 值也定义为宏? Like instead of writing everywhere
FORMAT(8,3)
, I would like to writeFORMAT(X, Y)
where I defined above#define X 8
and#define Y 3
.我不想到处写
FORMAT(8,3)
,而是想在上面定义的地方写FORMAT(X, Y)
#define X 8
和#define Y 3
。
Yes, there is a way to do that.是的,有办法做到这一点。 Introduce an extra macro:
引入一个额外的宏:
#define STR(z) #z
And invoke that on the arguments to FORMAT
, as shown here:并在 arguments 上将其调用为
FORMAT
,如下所示:
/* SO 7531-4669 */
#include <stdio.h>
#define STR(z) #z
#define FORMAT(x,y) "%+-" STR(x) "." STR(y) "lf"
#define Y 4
#define X 8
struct Point { double x, y, z; };
int main(void)
{
struct Point b = { 7123.4567, 6234.5678, 5345.6789 };
struct Point *a = &b;
printf("[" FORMAT(X, Y) ", " FORMAT(X, Y) ", " FORMAT(X, Y) "]\n",
a->x, a->y, a->z);
printf("[" FORMAT(8, 3) ", " FORMAT(8, 3) ", " FORMAT(8, 3) "]\n",
a->x, a->y, a->z);
return 0;
}
This works and produces the output:这有效并产生 output:
[+7123.4567, +6234.5678, +5345.6789]
[+7123.457, +6234.568, +5345.679]
It demonstrates that you can use simple numbers or macros that map to simple numbers as the arguments to this FORMAT
macro.它演示了您可以使用简单数字或宏,即 map 到简单数字,如 arguments 到此
FORMAT
宏。 What you can't do is have #define Y 3
and #define X (Y + 6)
— that will stringify (3 + 6)
which isn't valid in a printf()
conversion specification.您不能做的是
#define Y 3
和#define X (Y + 6)
— 这将对(3 + 6)
进行字符串化,这在printf()
转换规范中是无效的。 (Beware of making X
too big; you can end up with spaces between your number and the following comma. Experiment with #define X 12
to see what I mean.) (注意不要让
X
太大;你的数字和后面的逗号之间可能会有空格。 #define X 12
看看我的意思。)
The technique of invoking another macro triggers the expansion of the argument, which is often what you want.调用另一个宏的技术会触发参数的扩展,这通常是您想要的。 See How to make a char string from a C macro's value?
请参阅如何从 C 宏的值生成 char 字符串? and Macro directives in C — my code example doesn't work .
和C 中的宏指令 — 我的代码示例不起作用。 The Q&A How can I concatenate twice with the C preprocessor and expand a macro as in "
arg ## _ ## MACRO
"?问答如何使用 C 预处理器连接两次并扩展宏,如“
arg ## _ ## MACRO
”? is about token concatenation rather than stringification, but the issues are closely related, and the solutions are similar.是关于令牌连接而不是字符串化,但问题密切相关,解决方案相似。
You could adjust the macro to something like:您可以将宏调整为:
#define SPEC "lf"
#define FORMAT(x, y) "+-"#x"."#y SPEC
and call printf
:并致电
printf
:
printf("%"FORMAT(3, 20), x)
It might also be a good idea to place %
inside the macro.将
%
放在宏中也可能是个好主意。
The single hash (#), "converts" x and y arguments to string literals.单个 hash (#),将 x 和 y arguments “转换”为字符串文字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.