C言語利用va_list、va_start、va_end、va_argマクロ定義可変パラメータの関数

2207 ワード

可変パラメータの関数を定義する前に、関数パラメータの伝達原理を理解します.
1、関数パラメータはスタックのようなデータ構造でアクセスされ、関数パラメータリストでは右から左に順にスタックに入る.
2、パラメータのメモリ格納フォーマット:パラメータのメモリアドレスはメモリのスタックセグメントに格納され、関数を実行する時、最後の(一番右の)パラメータからスタックに入る.そのためスタックの底の高いアドレス、スタックの上の低いアドレス、例を挙げて説明する:
void test(int a, float b, char c);
では、test関数を呼び出すとき、実参char c先進スタック、それからfloat b、最後にint aとなるので、メモリにおける変数の格納順序はc->b->aである.理念的には、任意の変数のアドレスを検出するだけでなく、他の変数のタイプを知っていて、ポインタシフト演算によって、他の入力変数を見つけることができます.
可変パラメータの関数を実装するには、次のマクロを使用します.
typedef char* va_list;	//                     
void va_start(va_list ap, prev_param);	//                   ,                ,                    
void va_arg(va_list ap, type);	//                   ,               
void va_end(va_list ap);//                (   NULL)
、デモサンプル:N個の数の和を求める
int sum(int count, ...)
{
    int sum = 0;
    int i;
    va_list ap;
    va_start(ap, count);
    for (i = 0; i < count; ++i)
    {
        sum += va_arg(ap, int);
    }
    va_end(ap);
    return sum;
}
int main(int argc, const char * argv[])
{
    int ret = sum(5, 1, 2, 3, 4, 5);
    printf("sum: %d
",ret); }
4、
デモの例:標準ライブラリの可変パラメータに関する関数の使用
void test(int count,...)
{
    va_list ap;
    va_start(ap, count);
    vprintf("%d,%d,%d
", ap); // char buff[1024]; vsprintf(buff, "a=%d,b=%d,c=%d
", ap); // printf("%s
",buff); vfprintf(stdout, "a=%d,b=%d,c=%d
", ap); // // int vsscanf("10,30,40", "%d,%d,%d", ap); // , vsnprintf(buff, 30, "a=%d,b=%d,c=%d", ap); // , (30 ) printf("vsnprintf=%s
",buff); va_end(ap); }