嵌入式C开发基础题(13)之C的变长参数

13:此题考查的是C的变长参数

#include<stdio.h>
#include<stdarg.h>

int ripple ( int , ...);
void main()
{
	int num;
	num= ripple (3,5,7);
	printf(" %d\n" , num);
}

int ripple (int n, ...)
{
	int i,j;
	int k;
	va_list p;
	k=0;
	j= 1;
	va_start(p,n);
	for(; j<n; ++j)
	{
		i= va_arg( p , int);
		for(; i; i &= i-1 )
			++k;
	}
	return k;
}


这段程序的输出是:

(a)7 (b) 6 (c) 5 (d) 3


解答:


C编译器通常提供了一系列处理可变参数的宏,以屏蔽不同的硬件平台造成的差异,增加程序的可移植性。这些宏包括va_startva_argva_end等。 


采用ANSI标准形式时,参数个数可变的函数的原型声明是: typefuncname(type para1, type para2, ...) 


这种形式至少需要一个普通的形式参数,后面的省略号不表示省略,而是函数原型的一部分。type是函数返回值和形式参数的类型。

不同的编译器,对这个可变长参数的实现不一样gcc4.x中是内置函数.

关于可变长参数,可参阅 

http://www.upsdn.net/html/2004-11/26.html

http://www.upsdn.net/html/2004-11/24.html


程序分析

va_list  p; /*定义一个变量,保存函数参数列表 的指针*/
va_start(p , n); /*用va_start宏初始化 变量p,va_start宏的第2个参数n,是一个固定的参数,
				   必须是我们自己定义的变长函数的最后一个入栈的参数
				   也就是调用的时候参数列表里的第1个参数*/
for(; j<n; ++j) /* j从1开始,遍历所有可变参数*/
{
	i= va_arg( p , int); /*va_arg取出当前的参数,并认为取出的参数是一个整数(int)*/
	for(; i; i &=i-1 ) /*判断取出的i是否为0*/
		++k;/* 如果i不为0,k自加,
			   i与i-1进行与逻辑运算,直到i为0
			   这是一个技巧,下面会谈到它的功能*/
}


当我们调用ripple函数时,传递给ripple函数的参数列表的第一个参数n的值是3.

va_start初始化p指向第一个未命名的参数(n是有名字的参数),也就是5 (第一个).

每次对va_arg的调用,都将返回一个参数,并且把p指向下一个参数.【从左往右?】

va_arg用一个类型名来决定返回的参数是何种类型,以及在var_arg的内部实现中决定移动多大的距离才到达下一个参数


(;i; i&=i-1) k++    /*计算i有多少bit被置1*/


5用二进制表示是(101)2

7用二进制表示(111)3

所以k返回 5 (2+3),


举个例子,就很好理解:

i=9 = 1001

i-1= 1000

(i-1)+1 = i

1000 +1 = 1001

因为ii-1的最右边的那位(最低位)肯定是不同,如果i&(i-1),那么最右边哪位肯定是0,反之亦然.    i & (i-1) 这个运算,在二相补的数字系统中,将会消除最右边的1


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值