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

原创 2015年11月19日 22:51:47

宏定义中有几个特殊的字符 #,##, #@,下面我们来介绍一下这几个特殊的符号,以及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


 

相关文章推荐

C++常见问题(三)——宏定义、const、static、sizeof的相关实例

宏定义、const、static、sizeof的相关实例

C/C++中的max/min函数宏定义问题

不要轻易修改自带的头文件,写代码一定要规范!
  • zjn21hx
  • zjn21hx
  • 2015年11月12日 22:59
  • 10226

C可变长参数表问题---stdarg.h宏定义va_start,va_arg,va_end

一、什么是可变参数 我们在C语言编程中有时会遇到一些参数个数可变的函数,例如printf()函数,其函数原型为:  int printf( const char* format, ...);  ...
  • weio147
  • weio147
  • 2016年11月28日 10:12
  • 100

巧妙使用offsetof宏定义,在c,c++开发中解决问题

根据一个已经分配空间的结构体指针a中的某个成员b的地址,来获取该结构体指针地址...

嵌入式c宏定义

  • 2015年12月08日 11:00
  • 133KB
  • 下载

c常用宏定义,很全面

  • 2009年09月30日 11:36
  • 37KB
  • 下载

USB Drivers 相关结构体和宏定义记录 <LDD3 学习笔记>

USB Drivers 相关数据结构记录

C_宏定义_技巧____

  • 2009年06月27日 23:52
  • 11KB
  • 下载

处理C预编译宏定义详解

  • 2011年03月19日 08:29
  • 188KB
  • 下载

Unity3D 多平台_预编译相关宏定义

API地址:http://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html 平台定义 UNIT...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c 中有关宏定义的相关问题
举报原因:
原因补充:

(最多只允许输入30个字)