当前位置:首页 > 芯闻号 > 充电吧
[导读]《C语言接口与实现》作为接口库,源文件中大量使用了可变参数表,这些到底是怎么使用的?先来看这几个例子,基本明白了可变参数表使用。后面部分从网上整理了原理:源程序:#include#include#in

《C语言接口与实现》作为接口库,源文件中大量使用了可变参数表,这些到底是怎么使用的?先来看这几个例子,基本明白了可变参数表使用。后面部分从网上整理了原理:

源程序:


#include#include#include//
// 使用示例1:追加串
// 
void Va_Fn1(char *dest, char *data, ...)
{
	va_list ap;
	char *p = data;	//指向第一个可变参数

	//第二个参数就是写 ... 前面那个
	va_start(ap, data);

	//遍历每一个可变参数,取出来使用
	while(1)
	{	
		//访问当前这个可变参数,先用,后遍历!!
		strcat(dest, p);

		p = va_arg(ap, char *);
		if (p == NULL) break;
	}


	//结束
	va_end(ap);
}

//
// 使用示例2:累加和
// 
int Va_Fn2(int a, ...)
{
	int ret = a;	//指向第一个参数
	int sum = 0;

	va_list ap;

	//第二个参数就是写 ... 前面那个
	va_start(ap, a);
	
	//遍历每一个可变参数,取出来使用
	while(1)
	{
		//先用,后遍历
		sum += ret;


		ret =va_arg(ap, int);
		if (ret == -1) break;
	}

	//结束
	va_end(ap);

	return sum;
}



//
// 使用示例3:使用数据结构
// 
typedef struct
{
	int x;
	int y;
}MY_TYPE;
void Va_Fn3(int n, MY_TYPE *p, ...)
{
	int i = 0;
	va_list ap;
	MY_TYPE *tmp = p;

	//第二个参数就是写 ... 前面那个
	va_start(ap, p);
	
	for(; ix, tmp->y);

		tmp = va_arg(ap, MY_TYPE *);
	}
	

	//结束
	va_end(ap);


}


//
// 使用示例4:稍复杂的可变参数表
//		(char *, int, int),		(char *, int, int), ......	
// 
void Va_Fn4(char *msg, ...)
{
	va_list ap;
	int i, j;
	char *str = msg;	//指向第一个参数
	
	//第二个参数就是写 ... 前面那个
	va_start(ap, msg);

	while(1)
	{
		//使用可变参数表,先使用
		i = va_arg(ap, int);
		j = va_arg(ap, int);
		printf("t%s---%d----%dn", str, i, j);

		//后遍历
		str = va_arg(ap, char *);	//第二个参数是【可变参数】的类型
		if (str == NULL) break;
	}

	//结束
	va_end(ap);

}


void main()
{
	//示例1
	char dest[1000] = {0};
	Va_Fn1(dest, "Hello ", "OK ", "欢迎 ", "Yes ", NULL);
	printf("示例1 = %sn", dest);


	//示例2
	int x = Va_Fn2(9, 9, 1, 3, 90, -1);
	printf("示例2 = %dn", x);

	//示例3
	MY_TYPE a, b, c;
	a.x = 100;
	a.y = 300;
	b.x = 1100;
	b.y = 1300;
	c.x = 6100;
	c.y = 6300;
	printf("示例3:n");
	Va_Fn3(3, &a, &b, &c);

	//示例4
	printf("示例4:n");
	Va_Fn4("Hello", 1, 2, "XYZ", 300, 600, "ABC", 77, 88, NULL);
}


输出:


示例1 = Hello OK 欢迎 Yes
示例2 = 112
示例3:
        100-----300
        1100-----1300
        6100-----6300
示例4:
        Hello---1----2
        XYZ---300----600
        ABC---77----88
Press any key to continue


原理:

1. 函数参数是以数据结构:栈的形式存取,从右至左入栈

2. 首先是参数的内存存放格式:参数存放在内存的堆栈段中,在执行函数的时候,从最后一个开始入栈。因此栈底高地址,栈顶低地址,举个例子如下:

void func(int x, float y, charz);
那么,调用函数的时候,实参char z 先进栈,然后是 float y,最后是 intx,因此在内存中变量的存放次序是 x->y->z,因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量的类型,通过指针移位运算,则总可以顺藤摸瓜找到其他的输入变量。<----这就是原理!!

3. 看源码(vc98/include/stdarg.h):(注意是X86相关的,不是mips,不是ALPHA的,不是PPC等等的!)

typedef char *  va_list;


#ifdef  _M_IX86




#define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )


#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap)      ( ap = (va_list)0 )


#elif   defined(_M_MRX000)

这里有复杂的宏,展开它:在“工程属性” —〉“C/C++”—〉“Project Options” 手工填入/P,然后rebuild,会产生于.cpp同名的.i文件,里面的宏被展开了。来看展开后的第一个函数:


void Va_Fn1(char *dest, char *data, ...)
{
	va_list ap;
	char *p = data;	

	
	( ap = (va_list)&data + ( (sizeof(data) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) );

	
	while(1)
	{	
		
		strcat(dest, p);

		p = ( *(char * *)((ap += ( (sizeof(char *) + sizeof(int) - 1) & ~(sizeof(int) - 1) )) - ( (sizeof(char *) + sizeof(int) - 1) & ~(sizeof(int) - 1) )) );
		if (p == 0) break;
	}


	
	( ap = (va_list)0 );
}


再看展开的第二个函数,这个较简单:


int Va_Fn2(int a, ...)
{
	int ret = a;	
	int sum = 0;

	va_list ap;

	
	( ap = (va_list)&a + ( (sizeof(a) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) );
	
	
	while(1)
	{
		
		sum += ret;


		ret =( *(int *)((ap += ( (sizeof(int) + sizeof(int) - 1) & ~(sizeof(int) - 1) )) - ( (sizeof(int) + sizeof(int) - 1) & ~(sizeof(int) - 1) )) );
		if (ret == -1) break;
	}

	
	( ap = (va_list)0 );

	return sum;
}



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭