Namespaces
Variants

Variadic arguments

From cppreference.net

可変引数関数は、異なる数の引数で呼び出すことができる関数です。

プロトタイプ宣言された 関数宣言 のみが可変引数とすることができます。これは ... の形式のパラメータで示され、パラメータリストの最後に現れなければなりません (少なくとも1つの名前付きパラメータに続く必要があります (C23まで) 。省略記号パラメータと先行するパラメータは , で区切られなければなりません。

// プロトタイプ宣言
int printx(const char* fmt, ...); // このように宣言された関数
printx("hello world");     // 1つの引数で呼び出し可能
printx("a=%d b=%d", a, b); // または複数の引数で呼び出し可能
int printz(...); // C23以降およびC++で有効
// C23までエラー: ...は少なくとも1つの名前付きパラメータの後に続く必要がある
// int printy(..., const char* fmt); // エラー: ...は最後でなければならない
// int printa(const char* fmt...);   // Cではエラー: ','が必要; C++では有効

function call において、可変引数リストの一部である各引数は、 default argument promotions として知られる特別な暗黙の変換を受けます。

可変個引数を使用する関数本体内部では、これらの引数の値は <stdarg.h> ライブラリ機能 を使用してアクセスできます:

ヘッダで定義 <stdarg.h>
可変個引数関数の引数へのアクセスを有効にする
(関数マクロ)
次の可変個引数関数の引数にアクセスする
(関数マクロ)
(C99)
可変個引数関数の引数のコピーを作成する
(関数マクロ)
可変個引数関数の引数の走査を終了する
(関数マクロ)
va_start va_arg va_end 、および va_copy が必要とする情報を保持する
(typedef)

目次

注記

旧式(プロトタイプなし) 関数宣言 では、後続の関数呼び出しで任意の数の引数を使用できますが、(C89以降)可変引数関数として宣言することは許可されていません。このような関数の定義では固定数のパラメータを指定する必要があり、 stdarg.h マクロを使用することはできません。

// 旧形式の宣言、C23で削除
int printx(); // この方法で宣言された関数
printx("hello world");     // 1つの引数で呼び出される可能性がある
printx("a=%d b=%d", a, b); // または複数の引数で呼び出される可能性がある
// これらの呼び出しの少なくとも1つは、関数が取るように定義されたパラメータの数に応じて、動作が未定義となる

#include <stdio.h>
#include <time.h>
#include <stdarg.h>
void tlog(const char* fmt,...)
{
    char msg[50];
    strftime(msg, sizeof msg, "%T", localtime(&(time_t){time(NULL)}));
    printf("[%s] ", msg);
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}
int main(void)
{
   tlog("logging %d %d %d...\n", 1, 2, 3);
}

出力:

[10:21:38] logging 1 2 3...

参考文献

  • C17規格 (ISO/IEC 9899:2018):
  • 6.7.6.3/9 関数宣言子(プロトタイプを含む) (p: 96)
  • 7.16 可変個引数 <stdarg.h> (p: 197-199)
  • C11標準 (ISO/IEC 9899:2011):
  • 6.7.6.3/9 関数宣言子(プロトタイプを含む) (p: 133)
  • 7.16 可変個引数 <stdarg.h> (p: 269-272)
  • C99規格 (ISO/IEC 9899:1999):
  • 6.7.5.3/9 関数宣言子(プロトタイプを含む) (p: 119)
  • 7.15 可変個引数 <stdarg.h> (p: 249-252)
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.5.4.3/5 関数宣言子(プロトタイプを含む)
  • 4.8 可変引数 <stdarg.h>

関連項目

C++ documentation for Variadic arguments