商务合作加Q:411239339

C语言中的可变参数及宏定义使用分析

浏览:309次阅读
没有评论

共计 2170 个字符,预计需要花费 6 分钟才能阅读完成。

今天看到了 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;
}

查看运行结果

C 语言中的可变参数及宏定义使用分析

上面的函数 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 语言中的可变参数及宏定义使用分析

 

下面我们在来看看 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;
}

上面的运行结果是:

C 语言中的可变参数及宏定义使用分析

#include <stdio.h>

#define LOG(...) printf("%s:%ds\n", __FILE__, __LINE__, ##__VA_ARGS__)

int main(int argc, char* argv[])
{LOG();
	
	return 0;
}

上面的运行结果是:

C 语言中的可变参数及宏定义使用分析

上面这些是我个人对可变参数的理解,错误请大家指正。

正文完
扫码赞助
post-qrcode
 0
lslzhang
版权声明:本站原创文章,由 lslzhang 于2014-05-06发表,共计2170字。
转载说明:除特殊说明外本站文章皆由果较瘦原创发布,转载请注明出处。
评论(没有评论)