好记性不如铅笔头

C && C++, 编程

宏返回值和可变参数宏

CONTENTS

宏返回值

以下内容转自【 http://blog.csdn.net/fjb2080/article/details/5174171 】,有删改。
在使用逗号表达式中有一点需要注意的是,在逗号表达式中不可以声明变量。
例如:

int n = (int a=5, ++a); //这是错误的

可以这样使用:

int a;
int n = (a=5, ++a);

那么n的值就是6;
另外在gcc中亦可用{}表达式作为返回值,如:

#define fucn1(a)  ({a= a+5; a;})

例如下面一个例子:

#include <stdio.h>  
    #define func(a) ({a=a+5; a;})  
    int main(void)  
    {  
        //int i;  
        //int a = (i=5, ++i);  
        int a=0;  
        int b = func(a);  
        printf("a=%d/n", a);  
        printf("b=%d/n", b);  
        return 0;  
    }  

输出:

a=5
b=5

GCC对于宏返回值的描述:【 http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

可变参数宏

以下内容转自【www.cnblogs.com/caosiyang/archive/2012/08/21/2648870.html 】,有删改。
C99中规定宏可以像函数一样带有可变参数,比如

#define LOG(format, ...) fprintf(stdout, format, __VA_ARGS__)

其中,…表示参数可变,__VA_ARGS__在预处理中为实际的参数集所替换

GCC中同时支持如下的形式

#define LOG(format, args...) fprintf(stdout, format, args)

其用法和上面的基本一致,只是参数符号有变化
有一点需要注意,上述的宏定义不能省略可变参数,尽管你可以传递一个空参数,这里有必要提到”##”连接符号的用法。
“##”的作用是对token进行连接,在上例中,format、__VA_ARGS__、args即是token,如果token为空,那么不进行连接,所以允许省略可变参数(__VA_ARGS__和args),对上述变参宏做如下修改

#define LOG(format, ...)     fprintf(stdout, format, ##__VA_ARGS__)
#define LOG(format, args...) fprintf(stdout, format, ##args)

自己写的小测试:

#include <stdio.h>

int calcnum(int a, int b)
{
    a = a+ b + 10;
    b = b+5;
    return b;
}

#define CALCNUM(a,b) \
({\
    a = a+ b + 10;\
    b = b+5;\
    b;\
})

#define LOGA(format, ...)   printf(format,__VA_ARGS__)
#define LOGB(format, ...)   printf(format,##__VA_ARGS__)
#define LOGC(format, xx...)   printf(format,##xx)       /*重命名可变参数*/

int main(void)
{
    int a = 3, b = 5;
    int result = calcnum(a,b);
    printf("result:%d a:%d b:%d\n", result,a,b);

    a = 3, b = 5;
    result = CALCNUM(a,b);
    printf("result:%d a:%d b:%d\n", result,a,b);/* 注意这里的ab和上面的值是不同的。 */

 /*无可变参数,无法编译通过。*/
//    LOGA("Hello World A\n");
    LOGB("Hello World B\n");
    LOGC("Hello World C\n");
    LOGA("Hello World A %s\n","OMG");
    LOGB("Hello World B %s\n","OMG");
    LOGC("Hello World C %s\n","OMG");

    return 0;
}

输出:

result:10 a:3 b:5
result:10 a:18 b:10
Hello World B
Hello World C
Hello World A OMG
Hello World B OMG
Hello World C OMG

 

发表评论

5 − 2 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据