c语言 宏 变长参数,科学网—C/C++中处理变长参数函数(Variadic Function)的几个宏 - 彭彬的博文...
近日在模式中進行非線性方程組求解時遇到變長參數函數的問題,以前從來沒有自己寫過變長參數的函數,于是補了一下課,將近日對該小問題的學習和理解整理如下。
一、變長參數函數(variadic function)[1,2]
其實我們在剛開始學習程序設計語言的時候就已經接觸到變長參數函數,最明顯的例子就是C中的printf函數,該函數的調用方式是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;
}
這個函數的目的是求任意多個數的平均值,從這個例子中可以學習變長參數函數的使用方法:
1、采用#inculde 語句添加實現變參函數所需要的頭文件
2、變長參數函數的聲明和定義中用...表示變參列表
3、在函數內部用va_list關鍵字聲明一個變參列表指針ap
4、用va_start將ap初始化為指向函數最后一個定參(在該例子中average函數的最后一個定參是count)處
5、用va_arg從變參列表中依次獲取參數
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],這些宏的定義和實現也有所差異。
二、GCC中的實現
在GCC的stdarg.h(/usr/lib/gcc/x86_64-redhat-linux/4.4.5/include)頭文件中可以看到如下內容:
……
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幾個宏。關于這些宏的實現,在gcc中沒有再找到其他信息,因為上面的定義中將va系列宏指向了_builtin_函數,這些函數編譯器能自動識別并做相應處理[5]。
三、VC中的實現
在VC中這些宏的實現方式有明確定義: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)這句體現了programmer的智慧,需要詳細分析才能理解,可參考[6]。額,注意到沒,貌似VC不支持va_copy喔[7]。
References:轉載本文請聯系原作者獲取授權,同時請注明本文來自彭彬科學網博客。
鏈接地址:http://blog.sciencenet.cn/blog-430991-700026.html
上一篇:讓linux掛載的移動硬盤具有執行權限
下一篇:Fortran學習筆記(3): 一些非常有用的Fortran函數庫
總結
以上是生活随笔為你收集整理的c语言 宏 变长参数,科学网—C/C++中处理变长参数函数(Variadic Function)的几个宏 - 彭彬的博文...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言enum能自定义吗,18、C语言
- 下一篇: android跨进程读写内存,Andro