C宏中的#x表示什么意思?

59

例如,我有一个宏:

#define PRINT(int) printf(#int "%d\n",int)

我有点知道结果。

但为什么#int代表整个事情?

我有点忘了这个细节。能否有人友好地给我一个提示?

谢谢!


可能是这个的重复问题 http://stackoverflow.com/questions/10676999/stringizing-operator - Omkant
4个回答

60

在这个上下文中(应用于宏定义中的参数引用),井号表示将此参数扩展为传递给宏的实参的文字文本。

在这种情况下,如果您调用PRINT(5),则宏扩展将是printf("5" "%d\n", 5);,它将打印5 5;并不是非常有用;但是如果您调用PRINT(5+5),宏扩展将是printf("5+5" "%d\n", 5+5);,它将打印5+5 10,稍微有点不那么平凡。

这个例子在C预处理器教程中有解释(顺便说一句,这是“c宏井号符”的Google搜索结果的第一个链接)。


这是GCC的特性还是ANSI C标准? - Anders Lind
2
@AndersLind:这是标准行为。请参阅§6.10.3.2/2,其中详细说明了“#”运算符的语义。 - dreamlax
4
实际上是5+510。字符串标记之间的空格被忽略(不转换为空格字符 )。 - Fredrick Gauss
2
现在这个问题是“c宏井号”的谷歌搜索结果中的第一个 :) - nsane
1
@FrancescoBoi 而对于第一个例子,将打印55而不是5 5 - user16217248
显示剩余3条评论

19

"#"可以显示变量的名称,最好将宏定义为这样:

#define PRINT(i) printf(#i " = %d\n", i)

并像这样使用它:

int i = 5;
PRINT(i);

显示结果:

i = 5

8
这是宏参数名称的一个不好的选择,但并不会有害(感谢dreamlax)。
基本上,如果我像这样写:
PRINT(5);

它将被替换为

printf("5" "%d\n",5);

或者
printf("5 %d\n",5);

这是一个名为字符串化的过程,其中#int被替换为其内容组成的字符串,5 -> "5"。

2
宏是由预处理器展开的,它对C类型系统一无所知。据我所知,在§6.10(预处理指令)中,“int”并没有违反任何规则,但我同意这是一个糟糕的选择。 - dreamlax
您提供的字符串化文档链接已失效,请更新。 - DeathByTensors
1
@DrewBuckley 已修复! - Karthik T
"5 %d\n" 错误 "5%d\n" 正确 - user16217248

3
“#”被称为字符串化运算符。字符串化运算符会在传递的参数周围添加引号并返回一个字符串。它仅用于需要参数的宏语句中。
#include<stdio.h> 

#define stringLiteral(sl) #sl

int main()
{
   char StringizeOpreator = 'a'; 
   printf(stringLiteral(StringizeOpreator));
   return 0;
}

在这里,stringLiteral 宏接收形式参数 sl 并返回 #sl。传递的实际参数是 StringizeOpreator 变量。返回语句 #sl 带有 # 运算符,将引号放在参数周围,例如 "StringizeOpreator" 并返回一个字符串。

因此,上述程序的输出是实际参数 'StringizeOpreator' 的名称,而不是传递的实际参数中存储的值。

output :
StringizeOperator
...
exitcode 0

请访问此链接了解更多信息: 字符串化运算符


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接