C言語編 標準ライブラリのリファレンス va_arg

先頭へ戻る

va_arg

概要 可変個実引数の値を返し、次の引数へ進む。
ヘッダ stdarg.h
形式 #define va_arg(ap, type) *((type*)((ap+=sizeof(type))-sizeof(type)))
引数 ap va_list型の変数。
type 実引数の型。
戻り値 実引数の値。
詳細 可変個の引数を持つ関数に渡された実引数の値を取得するための関数形式マクロ。
va_list が保持している情報を使って、次の実引数の値を type で指定した型で返す。さらに次回の呼び出しで、次の実引数を取得できるように、va_list の情報を書き換える。
また、「形式」が示す実装例のように、引数type で指定した型名の後ろに「*」を付けて使用されるため、「type*」が「type へのポインタ型」になるように指定しなければならない。
注意 va_start(C99以降では va_copy でも良い)と、va_end の呼び出しの間で呼ばなければならない。
最後の可変個実引数を超えて、値を取得しようとする行為は未定義の動作である。
可変個実引数の型と、type で指定する型は以下の2点を除いて、一致していなければ未定義の動作になる。「1.一方が符号付き整数型で、他方が符号なし整数型であり、値がどちらの型でも表現可能な場合」「2.一方が void* で、他方が文字型へのポインタである場合」
使用例
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>

void print(const char* format, ...);

int main(void)
{
    print( "ddcd", 10, 20, 'x', 30 );
    print( "ss", "abc", "def" );
    print( "dfc", 50, 3.3f, 'Z' );

    return 0;
}

/*
    標準出力へ任意の個数・型の値を出力する
    引数:
        format:     変換指定子を並べたもの。以下のいずれかとする。
                        d … 符号付き整数型
                        f … 浮動小数点型
                        c … 文字型
                        s … 文字列型
                    とする。
                    例えば、"dds" と指定すると、
                    後続の実引数が 整数型, 整数型, 文字列型 の順番で並んでいるものと判断される。
        ...:        出力する値のリスト
*/
void print(const char* format, ...)
{
    const char* p;
    va_list args;

    va_start( args, format );

    for( p = format; *p != '\0'; ++p ){
        switch( *p ){
        case 'd':
            printf( "%d ", va_arg(args, int) );
            break;
        case 'f':
            printf( "%f ", va_arg(args, double) );
            break;
        case 'c':
            printf( "%c ", va_arg(args, char) );
            break;
        case 's':
            printf( "%s ", va_arg(args, const char*) );
            break;
        default:
            assert( !"不正な変換指定" );
            break;
        }
    }
    printf( "\n" );

    va_end( args );
}

実行結果

10 20 x 30
abc def
50 3.300000 Z
関連 va_startva_end の呼び出しの間で使用する。
C99 では va_copy を使うこともある。
解説章 第52章


参考リンク



更新履歴

'2018/4/19 全体的に文章を見直し修正。
「ヘッダ」が誤っていたのを修正。「注意」をより詳細にした。

'2018/1/22 新規作成。



標準ライブラリのリファレンス(名前順)のトップページへ

標準ライブラリのリファレンス(ヘッダ別)のトップページへ

C言語編のトップページへ

Programming Place Plus のトップページへ


はてなブックマーク Pocket に保存 Twitter でツイート Twitter をフォロー
Facebook でシェア Google+ で共有 LINE で送る rss1.0 取得ボタン RSS
管理者情報 プライバシーポリシー