可変長引数
提供: cppreference.com
可変長引数関数は異なる個数の引数を用いて呼ぶことができる関数です。
新形式 (プロトタイプ付き) の関数宣言のみが可変長にできます。 これは ... 形式の仮引数によって表されます。 ... は仮引数リストの最後かつ少なくとも1個の名前付き引数の後でなければなりません。
// 新形式の宣言。int printx(constchar* fmt, ...);// この方法で宣言した関数は printx("hello world");// 1個の引数で呼んだり printx("a=%d b=%d", a, b);// 複数の引数で呼んだりできます。 // int printy(..., const char* fmt); // エラー、 ... は最後でなければなりません。// int printz(...); // エラー、 ... は少なくとも1個の名前付き引数の後でなければなりません。
関数呼び出しの際、可変長引数リストの部分に当たる実引数には、デフォルト引数昇格と呼ばれる特別な暗黙の変換が適用されます。
可変長引数を使用する関数の本体では、それらの引数の値は <stdarg.h> ライブラリの機能を用いてアクセスできます。
ヘッダ <stdarg.h> で定義 | |
可変長引数関数の引数にアクセスできるようにします (関数マクロ) | |
可変長引数関数の次の引数にアクセスします (関数マクロ) | |
(C99) | 可変長引数関数の引数をコピーします (関数マクロ) |
可変長引数関数の引数の巡回を終了します (関数マクロ) | |
va_start, va_arg, va_end, va_copy で使用される情報を保持します (typedef) |
目次 |
[編集]ノート
旧形式 (プロトタイプなし) の関数宣言は、その後の関数呼び出しで任意個の実引数を渡すことを許容しますが、 (C89 では) それらが可変長であることは許容されません。 そのような関数は定義では固定個の仮引数を指定しなければならず、 <stdarg.h>
のマクロは使用できません。
// 旧形式の宣言。int printx();// この方法で宣言した関数は printx("hello world");// 1個の引数で呼んだり printx("a=%d b=%d", a, b);// 複数の引数で呼んだりできます。// その関数が定義されたときに取る仮引数の個数に応じて// それらの呼び出しのいずれかが未定義動作になります。
[編集]例
Run this code
#include <stdio.h>#include <time.h>#include <stdarg.h> void tlog(constchar* 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...
[編集]参考文献
- C11 standard (ISO/IEC 9899:2011):
- 6.7.6.3/9 Function declarators (including prototypes) (p: 133)
- 7.16 Variable arguments <stdarg.h> (p: 269-272)