了解令牌粘贴

时间:2015-07-23 05:17:51

标签: c c-preprocessor

请考虑以下代码段

shouldPerformSegueWithIdentifier

编译并执行时打印HELLO。 请帮助理解#include<stdio.h> #define AB "HELLO" #define A "WORLD" #define MAC1 A##B void main(void) { printf(MAC1"\n"); } ##之间忽略A的原因。

同样,在编译以下代码时,会出现以下错误,

B
  

21.c:在功能âmainâ中:
  21.c:11:2:错误:在程序中流浪â#â   21.c:11:9:错误:预期â)在字符串常量之前

为什么会出现这种情况?

4 个答案:

答案 0 :(得分:2)

##预处理令牌用于令牌粘贴

宏定义中A##B的效果是生成令牌AB。因此printf(MAC1"\n")printf(AB"\n")相同。

令牌不被忽略&#34;它正在完成它的工作。

在您的第二个示例中,A#B只是字面意思A#B#在函数式宏中只有特殊含义。所以你的代码扩展为:

printf(A#B"\n");

这是一个错误,因为#不是预处理器之外的C语法的一部分。

答案 1 :(得分:1)

令牌#和##在宏扩展中很特殊。 '##'是令牌粘贴运算符。它在宏中需要2个符号并将它们绑定到一个符号中。这对于创建专用名称很有用。

#define LINE_COUNTER   static int line## __LINE__ =0; line ## __LINE__ ++;

这会创建一个变量,当行执行时,该变量会增加。它可以在同一个函数中多次使用,因为它具有基于行号的唯一名称。 (static int line_17 = 0; line_17 ++;)

'#'符号是字符串化运算符。它将后面的内容转换为字符串。

#define assert( x )  if( ! x ) { fprintf( stderr, "Assertion failed %s\n", #x ); exit(  1 ) }

答案 2 :(得分:0)

##连接符号。换句话说,A ## B表示不存在的AB。 如果你想做两个变量名的变量名,你可以这样使用:

#define newVar(x,y) x##y

int main()
{
    int newVar(my,Var); // int myVar;
    newVar(f,printf)(stdout,"Hello World"); // fprintf(stdout,"Hello World");
}

#取一个名字,然后把它变成一个字符串。例如

#define VARSTR(x) #x

int main()
{
    printf(VARSTR(myVar));
}

将“myVar”打印到字符串中(即使myVar不是main的变量,它也在宏替换中)

 #define "HELLO" "WORLD"

要连接字符串文字,它们只需要彼此相邻放置,之间没有其他有效标记。因此导致“HELLOWORLD”注意文字之间的空格被忽略,并且是不必要的。我用它来澄清它。

这将取代AA和BB,如下所示:

#include<stdio.h>
#define AA "HELLO"
#define BB "WORLD"
#define MAC1 AA BB
void main(void)
{
    printf(MAC1"\n"); // printf("HELLO" "WORLD""\n");
    // same as printf("HELLOWORLD\n");
}

答案 3 :(得分:0)

正如其他人指出的那样,##运算符用于创建新标记。 #define MAC1 A##B将创建定义为包含字符串AB的宏HELLO。这就是printf(MAC1"\n")打印&#34; HELLO&#34;的原因。如果要连接ABA表示的字符串,可以按如下方式定义MAC1

#define MAC1 AB A

然后,您的预处理程序将首先将AB B替换为"HELLO""WORLD,以便MAC1看起来像

#define MAC1 "HELLO""WORLD"

然后它会在它出现的任何地方替换MAC1。所以你的printf语句将是

printf("HELLO""WORLD""\n"); // --> HELLOWORLD