C99宏在评估后构建带引号的字符串文字

时间:2010-07-28 03:20:52

标签: string macros c99 literals expansion

我正在用C99开发一个嵌入式应用程序,该项目包含一些定义如下的整数常量:

#define LEVEL1     0x0000
#define LEVEL2     (LEVEL1 + 1)

因此,为了记录日志而跟踪这些值变得很有用,所以我想使用宏来从上面的评估的版本创建一个字符串文字。例如:

strncpy(str, STRING(LEVEL2), len);

理想情况下会评估为

strncpy(str, "0x0001", len);

甚至

strncpy(str, "0001", len);

使用带有#运算符的两阶段宏(由this question建议)几乎可以正常工作。它评估为

strncpy(str, "(LEVEL1 + 1)", len);

我想避免使用运行时函数 - 因此我尝试使用宏解决方案。建议?

2 个答案:

答案 0 :(得分:2)

由于预处理器字符串化器非常麻烦,因此在创建版本号和字符串化时都需要添加间接级别:

#define STRING1(s) #s
#define STRING(s) STRING1(s)

#define LEVEL(x) x
#define LEVEL1 LEVEL(1)
#define LEVEL2 LEVEL(2)

printf(STRING(LEVEL2));
//2

答案 1 :(得分:1)

你不能这样做,因为预处理器对C语言一无所知,因此无法进行评估。

我看到两个选项可以获得所需的结果:

手动评估

完全按照您希望它们出现的方式编写您的关卡并使用单个字符串化操作符:

#define LEVEL1 0x0000
#define LEVEL2 0x0001
#define STRING(x)   # x

strncpy(str, STRING(LEVEL2), len);

缺点是这容易出错并且可能与本地编码约定冲突。

运行时评估

使用其中一种字符串格式函数sprintfsnprintf

#define LEVEL1 0x0000
#define LEVEL2 0x0001

char level[7];
snprintf(level, sizeof level, "%#06x", LEVEL2);
strncpy(str, level, len);

这有你想避免的运行时开销。