red*_*una 3 c visual-studio c-preprocessor
我正在尝试使用预处理器技巧来声明一个魔术变量.像这样的东西:
DECLARE(x)
Run Code Online (Sandbox Code Playgroud)
应该扩展到
int _DECLARED_VARIABLE_x_LINE_12
Run Code Online (Sandbox Code Playgroud)
如果声明在输入源的第12行.我试图使用## token-pasting命令和__LINE__宏,但我要么__LINE__在那里得到一个未解释的" ",否则预处理器似乎完全忽略了我的行.我目前的猜测是:
#define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
Run Code Online (Sandbox Code Playgroud)
在这种情况下,通常的技巧是使用第二个宏.但是,这似乎不适用于GCC(MacOS X 10.6.4上的4.5.1),并且需要第三级宏:
#define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
#define DECLARE42(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
#define DECLARE41(x, line) DECLARE42(x, line)
#define DECLARE40(x) DECLARE41(x, __LINE__)
int DECLARE(y);
int DECLARE40(c) = 129;
Run Code Online (Sandbox Code Playgroud)
输出'gcc -E':
# 1 "magicvars.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "magicvars.c"
int _DECLARED_VARIABLE_y_LINE___LINE__;
int _DECLARED_VARIABLE_c_LINE_8 = 129;
Run Code Online (Sandbox Code Playgroud)
我不确定我是否有一个很好的解释为什么需要第三级宏.
我也很想知道在你创建它们之后你将如何引用这些变量.
在完成有效工作之前,我经历了许多变化:
#define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
#define DECLARE11(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
#define DECLARE10(x) DECLARE11(x, __LINE__)
#define DECLARE23(line) _LINE_ ## line
#define DECLARE22(x) _DECLARED_VARIABLE_ ## x
#define DECLARE21(x, line) DECLARE22(x) ## DECLARE23(line)
#define DECLARE20(x) DECLARE21(x, __LINE__)
#define DECLARE32(line) _LINE_ ## line
#define DECLARE31(x, line) _DECLARED_VARIABLE_ ## x ## DECLARE32(line)
#define DECLARE30(x) DECLARE31(x, __LINE__)
#define DECLARE42(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
#define DECLARE41(x, line) DECLARE42(x, line)
#define DECLARE40(x) DECLARE41(x, __LINE__)
int DECLARE(y);
int DECLARE10(z) = 12;
int DECLARE20(a) = 37;
int DECLARE30(b) = 91;
int DECLARE40(c) = 129;
Run Code Online (Sandbox Code Playgroud)
玩得开心解决为什么非工作的人无法工作.然而,他们确实指出了我的工作答案.(我注意到Sun C编译器在同一输入上产生与GCC基本相同的结果.)
在尝试寻找进一步的宏以进行递归替换之前,预处理器##从宏替换列表中删除运算符.这意味着您的引用会在它有机会被识别为并被实际行号替换之前被"粘合"到宏的其余部分.__LINE____LINE__
因此,如果要将行号嵌入宏中,除了通过宏参数传递它之外别无选择
#define DECLARE_(x, L) _DECLARED_VARIABLE_##x##_LINE_##L
#define DECLARE(x) DECLARE_(x, __LINE__)
Run Code Online (Sandbox Code Playgroud)
这将正式解决原始宏定义中的直接问题.
但是,由于C/C++预处理器规范中的另一个怪癖,这仍然无法正常工作:相邻的参数名称##将替换为相应的参数值,而不会在参数值中进行递归宏扩展.即,L将替换为__LINE__,而不首先更改__LINE__实际的行号.
为了确保参数的递归宏扩展L,需要在宏定义中引入另一个"间接级别"
#define DECLARE__(x, L) _DECLARED_VARIABLE_##x##_LINE_##L
#define DECLARE_(x, L) DECLARE__(x, L)
#define DECLARE(x) DECLARE_(x, __LINE__)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,处理DECLARE_(x, L)宏时,预处理器将L递归处理:首先用它替换它,__LINE__然后__LINE__用实际的行号替换.DECLARE__将收到完整的行号.