zoukankan      html  css  js  c++  java
  • C语言中宏定义之 ## 用于可变参数

    GCC 支持复杂的宏,它使用一种不同的语法,使你可以给可变参数一个名字,如同其它参数一样,比如:

    引用
    #define debug(format, args...) fprintf(stderr, format, args)


    这种定义可读性更强,也更容易描述。完整测试代码:

    引用
    #include <stdio.h>

    #define debug(format, args...) fprintf(stderr, format, args)

    int main()
    {
        char a[20] = "hello world ";
        int i = 10;
        debug("i = %d, %s", i, a);

        return 0;
    }


    运行输出

    引用
    beyes@linux-beyes:~/C/micro> ./mic.exe 
    i = 10, hello world


    但是上面的定义仍存在一点问题,如果把上面的代码改为下面的:

    引用
    #include <stdio.h>

    #define debug(format, args...) fprintf(stderr, format, args)

    int main()
    {

        debug("hello world ");

        return 0;
    }


    那么在编译时会提示以下错误

    引用
    beyes@linux-beyes:~/C/micro> gcc -g mic.c -o mic.exe
    mic.c: In function ‘main’:
    mic.c:10: error: expected expression before ‘)’ token


    提示缺少右边括号。这是因为,当宏展开后,"hello world " 代入 format,然而,在其后还紧跟着一个逗号,但是这个逗号后面是期望有 args 参数的,但这里却没有,所以宏不能展开完全,故而无法编译通过。那么,再改一下宏定义:

    引用
    #include <stdio.h>

    #define debug(format, args...) fprintf(stderr, format, ##args)

    int main()
    {
        debug("hello world ");

        return 0;
    }


    这时候,再编译运行及输出:

    引用
    beyes@linux-beyes:~/C/micro> gcc -g mic.c -o mic.exe
    beyes@linux-beyes:~/C/micro> ./mic.exe
    hello world


    编译通过,并正常输出。上面的代码,在 fprintf() 中的 args 前面加了两个 # 号 ##。
    ## 号的作用是
    如果可变参数部分( args...) 被忽略或为空,那么 "##" 操作会使预处理器 (preprocessor) 去掉它前面的那个逗号。如果在调用宏时,确实提供了一些可变参数,GNU C 也会正常工作,它会把这些可变参数放在逗号的后面;如果没有提供,它就会自动去掉前面的逗号,使宏结束展开 ---- 补充完右边括号。

    另外,假如按照 C99 的定义来用,改宏为:

    引用
    #define debug(format, args...) fprintf(stderr, format, ##__VA_ARGS__)


    那么编译会出错:

    引用
    beyes@linux-beyes:~/C/micro> gcc -g mic.c -o mic.exe
    mic.c:3:58: warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro
    mic.c:9:1: error: pasting "," and "__VA_ARGS__" does not give a valid preprocessing token
    mic.c: In function ‘main’:
    mic.c:9: error: ‘__VA_ARGS__’ undeclared (first use in this function)
    mic.c:9: error: (Each undeclared identifier is reported only once
    mic.c:9: error: for each function it appears in.)


    原因在于,args... 和 ##__VA_ARGS__ 是不匹配的,正确的匹配应该是:

    引用
    #define debug(format, ...) fprintf(stderr, format, ##__VA_ARGS__)


    注意,... 省略号对应的就是 __VA_ARGS__

    一般的,定义可变参数宏的一个流行方法,形如:

    引用
    #define DEBUG(args) (printf("DEBUG: "), printf args)
    if(n != 0) DEBUG(("n is %d ", n));


    这个方法的一个缺点是,要记住一对额外的括弧。

  • 相关阅读:
    20180925-2 功能测试
    【PL/SQL编程】循环语句
    【PL/SQL编程】条件语句
    【PL/SQL编程】变量和常量
    【PL/SQL编程】数据类型说明
    【PL/SQL编程】注释说明
    【PL/SQL编程】SQL与PL/SQL的区别
    【SQL查询】查询结果翻译成其他值_decode
    【SQL查询】日期的转换_to_date/to_char
    【SQL查询】视图_view
  • 原文地址:https://www.cnblogs.com/wizzhangquan/p/4451913.html
Copyright © 2011-2022 走看看