Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在宏中使用#_C_Macros_Preprocessor Directive - Fatal编程技术网

C 在宏中使用#

C 在宏中使用#,c,macros,preprocessor-directive,C,Macros,Preprocessor Directive,请解释代码 #include <stdio.h> #define A(a,b) a##b #define B(a) #a #define C(a) B(a) main() { printf("%s\n",C(A(1,2))); printf("%s\n",B(A(1,2))); } C(A(1,2)) B(A(1,2)) #包括 #定义A(A,b)A##b #定义B(a)#a #定义C(a)B(a) main() { printf(“%s\n”,C(A(1,2)); pr

请解释代码

#include <stdio.h>
#define A(a,b) a##b
#define B(a) #a
#define C(a) B(a)

main()
{
 printf("%s\n",C(A(1,2)));
 printf("%s\n",B(A(1,2)));
}
C(A(1,2))
B(A(1,2))
#包括
#定义A(A,b)A##b
#定义B(a)#a
#定义C(a)B(a)
main()
{
printf(“%s\n”,C(A(1,2));
printf(“%s\n”,B(A(1,2));
}
输出

十二,

A(1,2)

我不明白,第一个printf如何计算为12?
它与第二个类似,因为C宏只是B宏的包装器吗?

C预处理器有两个运算符#和##。#运算符将类似宏的函数的参数转换为带引号的字符串,其中##运算符连接两个标识符

#define A(a,b) a##b will concatenate a with b returning ab as string.
so A(1,2) will return 12
#define B(a) #a  will return a as string
#define C(a) B(a) will call previous one and return a as string.
so C(A(1,2)) = C(12) = B(12) = 12 (as string)
B(A(1,2)) = A(1,2) because A(1,2) is taken as an argument and returned as string A(1,2) 

函数类宏中使用了两个运算符:

  • ##
    使宏连接两个参数
  • #
    使输入有效地转换为字符串文字
A(A,b)
##
中,导致A与b连接。在
B(a)
中,
#
有效地从输入创建字符串文本。因此,扩展如下所示:

C(A(1,2)) -> C(12) -> B(12) -> "12"
B(A(1,2)) -> "A(1,2)"
因为对于
C(A(1,2))
,首先计算
A(1,2)
部分,使其变为12,所以这两个语句不像看上去那样相等


如维基百科中所述,您可以在以下位置阅读更多关于这些内容的信息。

##运算符(称为“令牌粘贴运算符”)连接 将两个令牌合并为一个令牌

#运算符(称为“字符串化运算符”)转换 将标记转换为字符串,适当地转义任何引号或反斜杠

如果要对宏参数的展开进行字符串化,必须 要使用两级宏:

不能将宏参数与其他文本合并并字符串化 这一切都在一起。但是,您可以编写一系列相邻的字符串 常量和字符串化参数:然后C编译器将组合 将所有相邻字符串常量合并为一个长字符串

还有:

原来#的定义是这样的 立即字符串化宏参数,而不进一步扩展它 (如果参数恰好是另一个宏的名称)

因此,类似地,沿着这些路线:

you're doing C(A(1,2)), 
which would roll to C(12), // since no #, so inner argument is expanded
and then to B(12)
// [since you've done two levels of macros in the code:
// 1. from C() to B(), and then, 2. B() to #a]
= 12 . 
然而,在第一种情况下,根据B(a)的定义,仅进行了1级严格化(因为它会因为#而立即严格化)


这里的混乱来自一个简单的规则

计算宏时,预处理器首先解析传递给宏的参数中的宏。但是,作为一种特殊情况,如果参数位于
#
的右侧或与
##
相邻,则它不会解析此类参数中的宏。这就是规则

您的第一个案例

#include <stdio.h>
#define A(a,b) a##b
#define B(a) #a
#define C(a) B(a)

main()
{
 printf("%s\n",C(A(1,2)));
 printf("%s\n",B(A(1,2)));
}
C(A(1,2))
B(A(1,2))
前置处理器首先应用定义为
B(a)
C(a)
宏。定义中的参数附近没有
#
#
(在
B(a)
中没有),因此预处理器必须解析参数中的宏:

A(1,2)
A(A,b)
的定义是
A##b
,其计算结果为
12

计算
C(a)
宏参数中的宏后,C宏变为:

C(12)
预处理器现在解析
C(a)
宏,根据其定义,该宏变为

B(12)
完成此操作后,预处理器再次计算结果中的宏,并应用
B(a)
宏,因此结果变为

"12"
您的第二个案例

#include <stdio.h>
#define A(a,b) a##b
#define B(a) #a
#define C(a) B(a)

main()
{
 printf("%s\n",C(A(1,2)));
 printf("%s\n",B(A(1,2)));
}
C(A(1,2))
B(A(1,2))
与第一种情况类似,预处理器首先应用
B(a)
宏。但这一次,宏的定义是这样的:参数前面有
。因此,将应用特殊规则,并且参数中的宏不会被计算。因此,结果立即变成:

"A(1,2)"
预处理器再次检查结果,试图找到更多要展开的宏,但现在所有内容都是字符串的一部分,宏不会在字符串中展开。因此,最终结果是:

"A(1,2)"

看到并感谢@PineForestRanch,我现在明白了。谢谢你的回答@js441Thanks@Am_I_确实很有帮助:)