C宏生成printf格式字符串

4

是否可以编写一个使用令牌连接的宏,以返回printf的格式? 例如:

#define STR_FMT(x) ...code-here...

STR_FMT(10) 扩展为 "%10s"

STR_FMT(15) 扩展为 "%15s"

... 等等。

因此,我可以在printf中使用这个宏:

printf(STR_FMT(10), "*");
2个回答

15

你可以这样做,但我认为最好使用 printf() 功能来动态指定字段大小和/或精度:

#include <stdio.h>

int main(int argc, char* argv[])
{
    // specify the field size dynamically
    printf( ":%*s:\n", 10, "*");
    printf( ":%*s:\n", 15, "*");

    // specify the precision dynamically
    printf( "%.*s\n", 10, "******************************************");
    printf( "%.*s\n", 15, "******************************************");

    return 0;
}

这样做的好处是不使用预处理器,您还可以使用变量或函数来指定字段宽度而不是字面值。


如果您决定改用宏,请间接使用 # 运算符(如果在其他地方使用了 ## 运算符,则也使用它),方法如下:

// macros to allow safer use of the # and ## operators
#ifndef STRINGIFY
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#endif

#define STR_FMTB(x) "%" STRINGIFY(x) "s"

否则,如果您决定使用宏来指定字段宽度,您将得到不希望的行为(如What are the applications of the ## preprocessor operator and gotchas to consider?中所述)。


2
+1 如果提到了%*,并且明白OP可能想要将变量而不是编译时常量传递给这个宏。 - R.. GitHub STOP HELPING ICE

7
#define STR_FMT(x) "%" #x "s"

1
未来参考,gcc现在将其标记为安全警告。使用字符串化构建printf替换被视为不安全的,因为宏参数的错误会导致易受内存布局攻击的二进制代码。 - Byron Hawkins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接