什么时候可以将变量的值传递给宏进行字符串化?
例如,本文中的代码适用于常量定义的宏。
#define MAX_STRING_LENGTH 20
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
{
...
char word[MAX_STRING_LENGTH+1];
scanf("%" STRINGIFY(MAX_STRING_LENGTH) "s", word);
...
}
Run Code Online (Sandbox Code Playgroud)
但是我不能将它与变量一起使用,例如:
{
...
int val = 20;
char word[MAX_STRING_LENGTH+1];
scanf("%" STRINGIFY(val) "s", word);
...
}
Run Code Online (Sandbox Code Playgroud)
因为编译成功并出现此警告:
warning: invalid conversion specifier 'v' [-Wformat-invalid-specifier]
scanf("%" STRINGIFY(var) "s", word);
~~~^~~~~~~~~~~~~
test2.c:4:22: note: expanded from macro 'STRINGIFY'
#define STRINGIFY(x) STRINGIFY2(x)
^
test2.c:5:23: note: expanded from macro 'STRINGIFY2'
#define STRINGIFY2(x) #x
^
<scratch space>:466:2: note: expanded from here
"var"
^
1 warning generated
Run Code Online (Sandbox Code Playgroud)
但代码的运行不会等待任何输入。
相反,在另一篇文章中,可以将变量传递给该宏:
#define PRINT(int) printf(#int "%d\n",int)
...
int var =8;
PRINT(var);
Run Code Online (Sandbox Code Playgroud)
这两种情况有什么区别?如何修改第一个以便它也接受变量?
我尝试%d在宏内部使用,但没有成功。
预处理器始终仅对令牌进行操作。
宏不是函数。您不向其传递变量(按值)。您传递一个令牌序列。在STRINGIFY(MAX_STRING_LENGTH)令牌序列中是MAX_STRING_LENGTH,在STRINGIFY(val)它中是令牌序列val。
MAX_STRING_LENGTH本身是一个宏,并且由于STRINGIFY定义的工作方式,宏将在将其转换为字符串文字之前由预处理器扩展。20依次应用到它的标记也是如此#,并且它生"20"成为字符串文字。
另一方面,val它不是宏,预处理器不会扩展它。它将保持令牌序列为val。事实上val,具有某个值的变量名称对预处理器来说没有任何意义,它只关心标记。所以val就转化为字面意思了"val"。
您从另一篇文章中带来的示例有效,因为它扩展为:
printf("var" "%d\n", var);
Run Code Online (Sandbox Code Playgroud)
变量名#int变成了文字,没有什么魔法可以让预处理器读取变量的值。事实var 8被打印只是因为var作为参数传递给printf! 它由%d说明符在运行时打印。
最后,在尝试预处理器时,在 prpeprocessing 完成之后、编译文件之前查看源文件总是有帮助的。该gcc -E标志(或编译器的等效标志)可以帮助您做到这一点。