当前位置:首页 > 芯闻号 > 充电吧
[导读]《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;
}



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

嵌入式开发作为信息技术领域的重要分支,其涉及的语言种类繁多,各具特色。这些语言的选择取决于目标平台的特性、性能需求、开发者的熟练程度以及项目的具体要求。本文将详细介绍几种常见的嵌入式开发语言,包括C语言、C++、汇编语言...

关键字: 嵌入式开发 C语言

Java语言和C语言是两种不同的编程语言,它们在语法、特性和应用领域上有许多差别。下面将详细介绍Java语言和C语言之间的差异以及它们各自的技术特点。

关键字: Java语言 C语言 编程

嵌入式系统是一种专门设计用于特定应用领域的计算机系统,它通常由硬件和软件组成,并且被嵌入到其他设备或系统中,以实现特定的功能。在嵌入式系统的开发过程中,选择适合的编程语言是至关重要的。C语言是一种被广泛应用于嵌入式系统开...

关键字: 嵌入式 计算机 C语言

C语言是一种广泛应用于软件开发领域的编程语言。它是由贝尔实验室的Dennis Ritchie在20世纪70年代初创建的,旨在为UNIX操作系统的开发提供一种高级编程语言。C语言具有简洁、高效、可移植性强等特点,因此成为了...

关键字: C语言 操作系统 应用程序

嵌入式系统是现代生活中无处不在的一部分。它们包括了我们的家电、汽车、智能手机、医疗设备等等。这些系统的工作必须高效、可靠,因为它们往往控制着生活中的关键方面。而C语言作为一种广泛用于嵌入式系统开发的编程语言,其质量和稳定...

关键字: 嵌入式系统 C语言 编程

在嵌入式系统开发领域中,C语言是使用最广泛的编程语言之一。它具有高效、灵活和可移植的特点,成为嵌入式系统设计师的首选语言。本文将介绍C语言编程的基本概念、特点以及在嵌入式系统开发中的应用。

关键字: 嵌入式系统 C语言 编程

C语言编译器是一种用于将C语言源代码转换为可执行程序的软件工具。它的主要功能是将C语言代码翻译成机器语言,以便计算机能够理解和执行。C语言编译器通常包括预处理器、编译器、汇编器和链接器等多个组件,它们协同工作以完成编译过...

关键字: C语言 编译器 Microsoft Visual C++

Matlab和C语言的区别是:1、用途不同;2、语法不同;3、运行速度不同;4、可移植性不同;5、代码管理不同。Matlab是一种数值计算和科学计算工具

关键字: matlab语言 C语言 系统编程

单片机是一种集成电路,它包含了中央处理器、存储器、输入输出接口和时钟等基本部件。单片机广泛应用于各种电子设备中,如家用电器、汽车电子、医疗设备等。单片机的使用领域已十分广泛,如智能仪表、实时工控、通讯设备、导航系统、家用...

关键字: 单片机编程 单片机 C语言

一直以来,嵌入式都是大家的关注焦点之一。因此针对大家的兴趣点所在,小编将为大家带来嵌入式的相关介绍,详细内容请看下文。

关键字: 嵌入式 C语言
关闭
关闭