关闭

c 中有关宏定义的相关问题

145人阅读 评论(0) 收藏 举报
分类:

宏定义中有几个特殊的字符 #,##, #@,下面我们来介绍一下这几个特殊的符号,以及c99中几个特殊的宏定义,__VA_ARTGS__, __LINE__, __FILE__,__FUNCTION__ 这几个宏有着特殊的意义,其中__VA_ARGS__只能出现在c99的宏定义中(表示宏定义中的可变参数列表)


# 标准解释 带参数的宏定义中 参数字符串化,也就是说在宏定义体中把红参数用双引号扣起来。(表示它是一个字符串,而不是一个变量)#必须出现在参数前边
##  在带参数的宏定义中 连接两个参数,把两个参数粘结在一起。(注意不是连接成字符串,不会用双引号阔气),这个在可变参数宏定义中还有一个作用就是在参数为0是去掉前面的逗号,不过这是要放在参数前面例如 ##args
#@ 在带参数的宏定义中 吧参数展开成字符就是' '的展开, #@必须出现在参数前边
以上三个符号和参数间都可以有空格。例如 # a , b ## a, #@ a 都可以。


1.带参数的宏 参数和返回值是形参 是没有类型的,返回值是没有的,在宏展开中才有实际的返回值和参数类型。
2.带参数的宏定义,宏名称和左括号不能有空格,否则宏就会把它展开为普通宏。 例如  #define A(a,c) 正常,而#define A (A C) 错不能表达本意
3.传入参数前后忽略空格,#define  expect(a)      #a, 则char s = expect(   abc )  展开为 s = "abc"
4.如果宏定义中出现了# 或者## 那么它两边测参数不能做宏展开, 如果宏定义中出现了自己的宏定义也不展开。


下面举例说明:
  #define  STR(s)      #s        //#和参数之间可以有空格, 宏明和左括号之间不能有空格
  #define  TOCHAR(c)     #@c   ////#和参数之间可以有空格
  #define  STRCAT(s1,s2)      s1##s2      //##和参数之间可以有空格,


   void main(void)
  {
            printf("this is the string=%s\n", STR(abc));                 //展开为 "abc"
            printf("this is a char=%c\n", TOCHAR(a));                 //展开为 'a'
            int num = STRCAT(a,b);                                                //展开为  int num = ab;
  }                  


char string = STRAT(STR(a),STR(b));                    //这里指挥展开为,STR(a)STR(b) 而STR不会再展开了因为STRCAT展开后有##


上面的语句要想得到STR展开后的效果就的加一层宏转换,
#define     _STRCAT(S1,S2)        S1##S2
#define     STRCAT(s1,s2)         _STRCAT(s1,s2)


这样就先进行参数展开在进行宏替换,char string = STRCAT(STR(a),STR(b))         先替换成char sting=_STRCAT("a”,“b”) 再去进行替换。


最后介绍几个特殊的宏定义:

##__VA_ARGS__, __FILE__, __LINE__ 和__FUNCTION__,下面介绍一下这几个宏:

    1. __VA_ARGS__ , 这是一个可变参数的宏, 宏前面加一个##相当于当可变参数为0时,这里的##的作用就是把前面多余的“,“ 去掉的作用,不然编译不过。

     2. __FILE__ 这个宏的表示当前文件名

    3. __LINE__表示当前行号

    4. __FUNCTION__ 表示当前函数名

例如:

 #define PR(...)   printf(__VA_ARTGS__)    //这种只在c99中支持,宏前面没有“,"所以无需加##在宏前面没有多余的逗号,

  #define PR(format, ...)  printf(format, ##__VA_ARGS__)    //这也只有c99支持, 要件##因为在宏之前有逗号,如果参数可数为0就多一个逗号,

在c98中想要定义一个可变参数的宏,必须通过可变参数的函数来实现,不然不可能:

上面的也可以在c89中 这样定义

void prt(char str, ...)

{

     va_list args;

      va_start(args.str);

      printf("-----%s,%s\n",str,args);

      va_end(args);

}

#define PR(format,args...)    prt(format,##args)     //这种写法是c89所支持的,他宏定义中不支持可变参数, args...  和##args只能出现在宏定义中,在宏定义中args... 就表示可变参数。在函数中不能这样写最后一个参数和可变参数(...)间不能有其他字符只能是逗号 。形如:上例中的prt函数。如果加了会出错,编译器把他当成可变参数的类型了。


无论c98 还是c99 省略号只能代替最后面的参数

#define W(x,  ... ,  y) 是错误的。

int main()
{
    int wt=1,sp=2;
    PR("hello\n");
    PR("weight = %d, shipping = %d",wt,sp);
    return 0;
}
输出结果:
hello
weight = 1, shipping = 2


 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7097次
    • 积分:359
    • 等级:
    • 排名:千里之外
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条