'C、C++中#define宏定义中的#-##-@#详解'

  发布日期:   2018-11-02
  最新修改:   2020-07-05
  阅读次数:   197 次

###@#\的用法

  • 示例如下

      #define Conn(x,y) x##y 
      #define ToChar(x) #@x 
      #define ToString(x) #x

(1)##,连接操作符

  • 宏定义中:参数名,即为形参,如#define sum(a,b) (a+b);中a和b均为某一参数的代表符号,即形式参数。

  • 而##的作用则是将宏定义的多个形参成一个实际参数名。

  • 例如:

      #define exampleNum(n) num##n
    
      int num9=9;
  • 使用:

      int num=exampleNum(9); 将会扩展成 int num=num9;

注意:

  • 1.当用##连接形参时,##前后的空格可有可无。

      如:#define exampleNum(n) num ## n 相当于 #define exampleNum(n) num##n
  • 2.连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义

      #include <stdio.h>
      #define paster( n ) printf_s( "token" #n " = %d", token##n )
      int token9 = 9;
      int main()
      {
         paster(9);
      }
      运行结果:
      token9 = 9
  • 另外,如果##后的参数本身也是一个宏的话,##会阻止这个宏的展开。

        #define STRCPY(a, b)    strcpy(a ## _p, #b)
        int main()
        {
            char var1_p[20];
            char var2_p[30];
            strcpy(var1_p, "aaaa");
            strcpy(var2_p, "bbbb");
            STRCPY(var1, var2);
            STRCPY(var2, var1);
            printf("var1 = %s/n", var1_p);
            printf("var2 = %s/n", var2_p);
            return 0;
    
            /* 注意这里 */
            STRCPY(STRCPY(var1,var2),var2);
            /* 这里是否会展开为: strcpy(strcpy(var1_p,"var2")_p,"var2“)?
             * 答案是否定的:
             * 展开结果将是:  strcpy(STRCPY(var1,var2)_p,"var2")
             * ## 阻止了参数的宏展开!
             * 如果宏定义里没有用到 # 和 ##, 宏将会完全展开
             */
        }  

(2)#@,字符化操作符

  • 只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。作用是将传的单字符参数名转换成字符,以一对单引用括起来。

      #define makechar(x)  #@x
    
      a = makechar(b);
    
      展开后变成了:
    
      a= 'b';

(3)#,字符串化操作符

  • 其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名字符串。其只能用于有传入参数的宏定义中,且必须置于宏定义体中的参数名前。

  • 例如:

      #define example(instr) printf("the input string is:/t%s/n",#instr)
    
      #define example1(instr) #instr
  • 当使用该宏定义时:

    example(abc); 在编译时将会展开成:printf("the input string is:/t%s/n","abc");
    
    string str=example1(abc); 将会展成:string str="abc";

注意:对空格的处理

  • a。忽略传入参数名前面和后面的空格。

       如:str=example1(   abc ); 将会被扩展成 str="abc";
  • b.当传入参数名间存在空格时,编译器将会自动连接各个子字符串,用每个子字符串中只以一个空格连接,忽略其中多余一个的空格。

       如:str=exapme( abc    def); 将会被扩展成 str="abc def";

(4)\ 行继续操作

  • \ 行继续操作当定义的宏不能用一行表达完整时,可以用""表示下一行继续此宏的定义注意:最后一行不要加续行符啊.VC的预处理器在编译之前会自动将\与换行回车去掉(写成多行时,反斜杠后不能有空格,否则编译器(ARM或VC)会报错!)

   转载规则

《'C、C++中#define宏定义中的#-##-@#详解'字》GajAngels 采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。