今天看到了c语言的中可变参数宏定义,以前没见过,上网查了点资料,让我们先看看c语言中可变参数函数吧。下面是c语言中printf函数的声明
int printf(const char* str, ...);
你可以看到printf的第二个参数是三个.,这就是c语言中的可变参数使用。那么我们如何定义我们自己的可变函数了,首先你要包含#include<stdarg.h>头文件来使用里面四个内置的宏,va_list, va_start, va_arg, va_end;下面定义定义一个我们自己的可变参数
#include <stdarg.h> #include <stdio.h> int add(int len, ...) { int i = 0; int sum = 0; va_list va; va_start(va, len); for(i=0; i<len; i++) { sum += va_arg(va, int); } return sum; } int main(int argc, char* argv[]) { printf("add(5) = %d\n", add(5, 1, 2, 3, 4, 5)); printf("add(3) = %d\n", add(3, 1, 2, 3)); return 0; }
查看运行结果
上面的函数add函数式一个可变参数函数,第一个参数是固定,这个是定义一个可变参数的的必须条件,用于得到虚参在栈里面的首地址,函数的功能实现指定个整数的和,第一个参数指定数的个数。下面我们分析add函数,首先va_list声明一个变量,
va_list可能是这样一个#define va_list void*宏定义,
va_start可能是这样一个#define va_start(va, len) (va = (void*)((char*)&len + sizeof(len))),va_start宏是通过第一个固定参数len来给找到第一个可变参数(c语言中函数入栈是从右向左的)的地址,既va变量里面存放的就是我们第一个可变参数的首地址
va_arg可能是这样一个#define va_arg(va, int) *((int*)(va = (void*)((int*)va + 1)) - 1)宏定义,用于得到其中的某个变参的值
va_end可能是这样一个#define va_end(va) va = NULL;
经过我们上面的分析我们可以去掉我们第一次包含的#include <stdarg.h>头文件,所用我们自定义的宏,例如下面的代码:
#include <stdio.h> #define va_list void* #define va_start(va, len) (va = (void*)((char*)&len + sizeof(len))) #define va_arg(va, int) *((int*)(va = (void*)((int*)va + 1)) - 1) #define va_end(va) va = NULL; int add(int len, ...) { int i = 0; int sum = 0; va_list va; va_start(va, len); for(i=0; i<len; i++) { sum += va_arg(va, int); } return sum; } int main(int argc, char* argv[]) { printf("add(5) = %d\n", add(5, 1, 2, 3, 4, 5)); printf("add(3) = %d\n", add(3, 1, 2, 3)); return 0; }
这次我们没有包含#include <stdarg.h>头文件,看看运行结果和上面的运行结果一致.
下面我们在来看看c语言中可变参数宏定义(不要第一个参数为固定参数,宏只是简单的文本替换),先来看看一个定义
#define LOG(arg...) printf("%s:%d:%s", __FILE__, __LINE__, arg),__FILE__和__LINE__是c语言中内置的宏,用于显示当前文件名和行号,这里我们使用了arg这个名字,如果在定义的时候没有写名字,例如像这样
#define LOG(...) printf("%s:%d:%s", __FILE__, __LINE__, __VA_ARGS__)我们可以使用__VA_ARGS__这个宏来代替
这里还有一个##号的用法,放在__VA_ARGS__的前面,例如像这样
#define LOG(...) printf("%s:%d:%s", __FILE__, ___LINE__, ##__VA_ARGS__), 当我们以LOG(); 调用时,会自动去掉__LINE__后面的逗号,下面是一个测试例子
#include <stdio.h> #define LOG(arg...) printf("%s:%d:%s\n", __FILE__, __LINE__, arg) int main(int argc, char* argv[]) { LOG("hello world!"); return 0; }
上面的运行结果是:
#include <stdio.h> #define LOG(...) printf("%s:%ds\n", __FILE__, __LINE__, ##__VA_ARGS__) int main(int argc, char* argv[]) { LOG(); return 0; }
上面的运行结果是:
上面这些是我个人对可变参数的理解,错误请大家指正。
- 微信扫码赞助
- 支付宝赞助