c语言 宏 变长参数,科学网—C/C++中处理变长参数函数(Variadic Function)的几个宏 - 彭彬的博文...
近日在模式中進行非線性方程組求解時遇到變長參數(shù)函數(shù)的問題,以前從來沒有自己寫過變長參數(shù)的函數(shù),于是補了一下課,將近日對該小問題的學習和理解整理如下。
一、變長參數(shù)函數(shù)(variadic function)[1,2]
其實我們在剛開始學習程序設計語言的時候就已經(jīng)接觸到變長參數(shù)函數(shù),最明顯的例子就是C中的printf函數(shù),該函數(shù)的調(diào)用方式是printf(format,varibale_list),我們可以一次輸出很多個變量,只要在format字符串中用%定義了這些變量的類型。再拿Wiki中的一段小程序[1]作為例子:
#include
double average(int count, ...)
{
va_list ap;
int j;
double tot =0;
va_start(ap, count);/* Requires the last fixed parameter (to get the address) */
for(j =0; j < count; j++)
tot +=va_arg(ap,double);/* Increments ap to the next argument. */
va_end(ap);
return tot / count;
}
這個函數(shù)的目的是求任意多個數(shù)的平均值,從這個例子中可以學習變長參數(shù)函數(shù)的使用方法:
1、采用#inculde 語句添加實現(xiàn)變參函數(shù)所需要的頭文件
2、變長參數(shù)函數(shù)的聲明和定義中用...表示變參列表
3、在函數(shù)內(nèi)部用va_list關鍵字聲明一個變參列表指針ap
4、用va_start將ap初始化為指向函數(shù)最后一個定參(在該例子中average函數(shù)的最后一個定參是count)處
5、用va_arg從變參列表中依次獲取參數(shù)
6、用va_end將變參列表指針釋放
那va_list類型以及va_start、va_arg、va_end到底是什么呢?答案是:宏。這些宏的定義位于stdarg.h(C)或者cstdarg.h(C++)中,包括上面提到的va_list類型以及va_start、va_end、va_arg和va_copy宏[3]。由于硬件平臺和編譯平臺的不同[4],這些宏的定義和實現(xiàn)也有所差異。
二、GCC中的實現(xiàn)
在GCC的stdarg.h(/usr/lib/gcc/x86_64-redhat-linux/4.4.5/include)頭文件中可以看到如下內(nèi)容:
……
typedef __builtin_va_list __gnuc_va_list;
……
typedef __gnuc_va_list va_list;
……
#define va_start(v,l) ? __builtin_va_start(v,l)
#define va_end(v) ? ? ? __builtin_va_end(v)
#define va_arg(v,l) ? ? __builtin_va_arg(v,l)
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define va_copy(d,s) ? ?__builtin_va_copy(d,s)
#endif
#define __va_copy(d,s) ?__builtin_va_copy(d,s)
這說明gcc在這個頭文件中定義了va_list類型和va_start、va_end、va_arg、和va_copy幾個宏。關于這些宏的實現(xiàn),在gcc中沒有再找到其他信息,因為上面的定義中將va系列宏指向了_builtin_函數(shù),這些函數(shù)編譯器能自動識別并做相應處理[5]。
三、VC中的實現(xiàn)
在VC中這些宏的實現(xiàn)方式有明確定義:typedef char * ?va_list;#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 )
#define _INTSIZEOF(n)這句體現(xiàn)了programmer的智慧,需要詳細分析才能理解,可參考[6]。額,注意到?jīng)],貌似VC不支持va_copy喔[7]。
References:轉(zhuǎn)載本文請聯(lián)系原作者獲取授權,同時請注明本文來自彭彬科學網(wǎng)博客。
鏈接地址:http://blog.sciencenet.cn/blog-430991-700026.html
上一篇:讓linux掛載的移動硬盤具有執(zhí)行權限
下一篇:Fortran學習筆記(3): 一些非常有用的Fortran函數(shù)庫
總結
以上是生活随笔為你收集整理的c语言 宏 变长参数,科学网—C/C++中处理变长参数函数(Variadic Function)的几个宏 - 彭彬的博文...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

- 上一篇: c语言enum能自定义吗,18、C语言
- 下一篇: android跨进程读写内存,Andro