嵌入式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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章