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

发布于 2024-09-11 21:10:55 字数 644 浏览 12 评论 0原文

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

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

从那时起,跟踪这些值以用于记录目的变得很有用,因此我想使用宏从上述的评估版本。例如:

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

理想情况下会计算为

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

或什至

strncpy(str, "0001", len);

使用带有 # 运算符的两阶段宏(如 这个问题)几乎有效。它的评估结果是

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

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

I'm developing an embedded application in C99, and the project contains some integer constants defined like:

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

It has since become useful to keep track of these values for logging purposes, so I would like to use a macro to create a string literal from the evaluated versions of the above. For example:

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

would ideally evaluate to

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

or even

strncpy(str, "0001", len);

Using a two-stage macro with the # operator (as suggested by this question) almost works. It evaluates to

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

I would like to avoid the use of a run-time function - hence my attempt at a macro solution. Suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

原来是傀儡 2024-09-18 21:10:55

由于预处理器字符串生成器非常痛苦,因此您需要在创建版本号和字符串化时添加一定程度的间接:

#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

Since the pre-processor stringizer is a massive pain, you need to add a level of indirection both when creating version numbers and when stringizing:

#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
护你周全 2024-09-18 21:10:55

您不能这样做,因为预处理器对 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);

这具有您想要避免的运行时开销。

You cannot do this because the preprocessor knows nothing about the C language so it cannot to evaluation.

I see two options to get the desired result:

Manual evaluation

Write your levels exactly as you want them to appear and use a single stringizer operator:

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

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

A disadvantage is that this is error prone and might clash with local coding conventions.

Runtime evaluation

Use one of the string format functions sprintf or snprintf.

#define LEVEL1 0x0000
#define LEVEL2 0x0001

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

This has the runtime overhead you wanted to avoid.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文