gpt4 book ai didi

c - 在 C 预处理器中避免双重宏替换

转载 作者:IT王子 更新时间:2023-10-29 00:38:14 25 4
gpt4 key购买 nike

这是一个简单的小 C 程序,让我困惑了一段时间:

#include <stdio.h>
#define STR1(x) #x
#define STR(x) STR1(x)
int main(void) {
printf("%s\n", STR(MYDEF));
}

这只是使用标准的字符串化双定义技术将 MYDEF#define 的值打印为字符串。

使用 gcc -DMYDEF=abc prog.c 编译(在 Linux 上)运行结果,毫不奇怪,它会打印出“abc”。

但是更改值 gcc -DMYDEF=linux prog.c 并且打印的结果不是 'linux' 而是 '1'。

所以这让我有点困惑,但它当然会发生,因为我发现 gcc(在 Linux 上)有一个内置的 #define 用于名称“linux”,值为“1”,并且 STR( x) 宏最终将 MYDEF 扩展为“linux”,然后将 linux 扩展为“1”。

在我的真实程序中(它比上面的小测试要复杂得多)我通过以不同的(可能更好的)方式做事来解决这个问题,但这让我很好奇......是否有一个简单的小宏技术这样可以避免这种双重替换并使程序打印出“linux”吗?我知道我可以添加 Linux 的 -U 或 #undef,但这感觉有点笨拙。

我原以为所有内置的#defines 都以下划线开头(通常是双下划线),但我想不是。

最佳答案

没有办法只展开一个宏一次,总是有一个重新扫描执行进一步的替换(当然从不递归)。在某些情况下,宏根本不会扩展(与 # 运算符一样),这就是为什么您需要像示例中那样使用两个 #define 的额外替换级别.

在 ISO C 中,没有前导下划线的标识符供您免费使用(准确地说,不是全部)。 GNU C 方言默认定义了一些其他宏(如 linux)以实现向后兼容性,尽管他们计划在未来删除此类宏。

要在您的机器上获取此类宏的列表,您可以执行以下操作:

$ echo | gcc -std=gnu99 -E -dM - | grep -v '# *define  *_'
#define unix 1
#define linux 1
#define i386 1

使用 ISO C 的选项(-ansi/-std=c89-std=c99-std= c11/-std=c1x for older Gcc), 这些宏没有定义:

$ cat test.c     
#define STR1(x) #x
#define STR(x) STR1(x)
STR(MYDEF);
STR1(MYDEF);
$ gcc -std=gnu99 -DMYDEF=linux -E test.c
# 1 "test.c"
# 1 "<command-line>"
# 1 "test.c"


"1";
"MYDEF";
$ gcc -std=c99 -DMYDEF=linux -E test.c
# 1 "test.c"
# 1 "<command-line>"
# 1 "test.c"


"linux";
"MYDEF";

在 ISO C 模式下,这些宏正确地位于保留命名空间中:

$ echo | gcc -std=c99 -E -dM - | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

关于c - 在 C 预处理器中避免双重宏替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27533994/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com