Manpages

名 前

stdarg, va_start, va_arg, va_end, va_copy − 個 数 、 型 が 可 変 な 引 数 リ ス ト

書 式

#include <stdarg.h>

void va_start(va_list ap, last);
type
va_arg(va_list ap, type);
void va_end(va_list
ap);
void va_copy(va_list
dest, va_list src);

説 明

関 数 は 呼 び 出 し に 際 し て 、 個 数 や 型 が 可 変 な 引 数 を と る こ と が で き る 。 イ ン ク ル ー ド フ ァ イ ル <stdarg.h> で は va_list 型 が 宣 言 さ れ て お り 、 3 つ の マ ク ロ が 定 義 さ れ て い る 。 こ れ ら を 用 い る と 、 呼 び 出 さ れ た 関 数 側 で は 個 数 や 型 を 知 ら な い 引 き 数 の リ ス ト を 、 順 に 一 つ づ つ 読 み 込 む こ と が で き る 。 呼 び 出 さ れ る 関 数 で は 、 va_list 型 の オ ブ ジ ェ ク ト が 宣 言 さ れ て い な け れ ば な ら な い 。 こ の オ ブ ジ ェ ク ト が va_start(), va_arg(), va_end() の 各 マ ク ロ に よ っ て 扱 わ れ る 。

va_start()
va_start
() マ ク ロ は 最 初 に 呼 び 出 さ な け れ ば な ら な い 。 こ れ は ap を 初 期 化 し 、 va_arg() と va_end() で 用 い る こ と が で き る よ う に す る 。 引 き 数 last は 引 き 数 リ ス ト の う ち 、 可 変 な 部 分 の 直 前 に 置 か れ る 引 き 数 の 名 前 で あ る 。 つ ま り 呼 び 出 さ れ た 関 数 が 型 を 知 っ て い る 最 後 の 引 き 数 で あ る 。 こ の 引 き 数 は レ ジ ス タ ー 変 数 や 関 数 、 配 列 と し て 宣 言 し て は な ら な い 。 こ の 引 き 数 の ア ド レ ス が va_start() マ ク ロ で 用 い ら れ る か も し れ な い か ら で あ る 。

va_arg()
va_arg
() マ ク ロ は 、 呼 び 出 し 時 に 指 定 さ れ た 引 き 数 の う ち 、 次 の 位 置 に あ る も の を 指 定 し た 型 type の 値 と し て 取 得 す る 。 引 き 数 apva_list ap で 、 va_start() に よ っ て 初 期 化 さ れ て い る 必 要 が あ る 。 va_arg() を 呼 び 出 す ご と に ap は 変 更 さ れ 、 次 回 の 呼 び 出 し の 際 に 、 さ ら に 次 の 引 き 数 を 返 す よ う に な る 。 引 き 数 type は 型 の 名 前 で あ る 。 type の 前 に * を 付 け れ ば 、 オ ブ ジ ェ ク ト へ の 型 付 き ポ イ ン タ ー が 得 ら れ る 。

va_start() マ ク ロ の 直 後 に va_arg() を 最 初 に 実 行 す る と 、 last の 次 の 引 き 数 が 返 る 。 続 け て 実 行 す る と 、 残 り の 引 き 数 が そ れ ぞ れ 返 る 。 次 の 引 き 数 が な か っ た り 、 type が 次 の 引 き 数 の 実 際 の 型 と 互 換 で な い 場 合 (デ フ ォ ル ト の 引 き 数 変 換 で 扱 え な か っ た 場 合 ) に は 、 予 測 で き な い エ ラ ー が 起 こ る 。

apva_arg(ap,type) の 形 で 関 数 に 渡 さ れ る と 、 ap の 値 は 関 数 か ら 返 っ て 来 た 後 は 不 定 と な る 。

va_end()
va_start
() が 実 行 さ れ る 毎 に 、 同 じ 関 数 内 で 対 応 す る va_end() が 実 行 さ れ な け れ ば な ら な い 。 va_end(ap) が 呼 び 出 さ れ た 後 、 変 数 ap の 値 は 不 定 と な る 。 va_start() と va_end() の 組 を 何 回 も 並 べ て 使 う こ と も 可 能 で あ る 。 va_end() は マ ク ロ か も し れ な い し 関 数 か も し れ な い 。

va_copy()
va_copy
() マ ク ロ は (初 期 化 済 み の ) 可 変 長 引 き 数 リ ス ト srcdest に コ ピ ー す る 。 動 作 は 、 last 引 き 数 に dest を 渡 し て va_start() を dest に 適 用 し 、 そ れ か ら src が 現 在 の 状 態 に 達 す る ま で に 呼 び 出 し た の と 同 じ 回 数 だ け va_arg() を 呼 び 出 す 、 の と 同 じ こ と を 行 う 。 す ぐ 分 か る va_list の 実 装 は 、 variadic な 関 数 の ス タ ッ ク フ レ ー ム の ポ イ ン タ ー で あ る 。 こ の よ う な 場 合 (ほ と ん ど は そ う で あ る )、 単 に 以 下 の よ う に す れ ば い い よ う に 思 え る 。

va_list aq = ap; 残 念 な が ら 、 (長 さ 1の )ポ イ ン タ ー の 配 列 と し て 扱 う シ ス テ ム も あ る 。 そ の よ う な 場 合 、 以 下 の よ う に す る 必 要 が あ る 。

va_list aq;
*aq = *ap; 最 後 に 、 引 き 数 を レ ジ ス タ ー で 渡 す シ ス テ ム の 場 合 、 va_start() で メ モ リ ー を 割 り 当 て 、 引 き 数 を 格 納 し 、 次 の 引 き 数 が ど れ か を 指 し 示 す よ う に す る 必 要 が あ る 。 そ し て va_arg() で リ ス ト を 順 番 に た ど り 、 va_end() で 割 り 当 て た メ モ リ ー を 開 放 す る 。 こ の よ う な 状 況 に 対 応 す る た め 、 C99 で は va_copy() マ ク ロ を 追 加 し 、 前 述 の よ う な 割 り 当 て は 以 下 の よ う に 置 き 換 え ら れ る よ う に し た 。

va_list aq;
va_copy(aq, ap);
...
va_end(aq);

va_copy() が 実 行 さ れ る ご と に 、 対 応 す る va_end() を 同 じ 関 数 内 で 実 行 し な け れ ば な ら な い 。 こ の 名 前 は ま だ draft proposal な の で 、 va_copy() の 代 わ り に __va_copy を 用 い る シ ス テ ム も あ る 。

属 性

マ ル チ ス レ ッ デ ィ ン グ (pthreads(7) 参 照 ) マ ク ロ va_start(), va_arg(), va_end(), va_copy() は ス レ ッ ド セ ー フ で あ る 。

準 拠

va_start(), va_arg(), va_end() マ ク ロ は C89 準 拠 で あ る 。 va_copy() は C99 で 定 義 さ れ て い る 。

注 意

こ れ ら の マ ク ロ は 、 以 前 か ら 用 い ら れ て き た 同 等 の マ ク ロ 群 と 互 換 で は な い 。 過 去 の も の と 互 換 な バ ー ジ ョ ン は 、 イ ン ク ル ー ド フ ァ イ ル <varargs.h> に 存 在 す る 。 歴 史 的 な セ ッ ト ア ッ プ は 以 下 の と お り で あ る 。

#include <varargs.h>

void
foo(va_alist)
va_dcl
{
va_list ap;

va_start(ap);
while (...) {
...
x = va_arg(ap, type);
... }
va_end(ap); }

va_start マ ク ロ に '}' を 含 み 、 va_end マ ク ロ に 対 応 す る '{' を 含 む シ ス テ ム も あ る の で 、 こ の 二 つ の マ ク ロ は 同 じ 関 数 に な け れ ば な ら な い 。

バ グ

varargs マ ク ロ と は 異 な り 、 stdarg マ ク ロ で は 固 定 引 き 数 な し で 関 数 を 指 定 す る こ と が 許 さ れ て い な い 。 こ れ は varargs ベ ー ス の コ ー ド を stdarg の コ ー ド に 書 き 換 え る と き に 、 面 倒 な 作 業 の も と に な る 。 ま た 、 す べ て の 引 き 数 を va_list と し て 可 変 個 指 定 し た い よ う な 場 合 (vfprintf(3) な ど ) に も 障 害 と な る 。

関 数 foo は 書 式 文 字 か ら な る 文 字 列 を 受 け 入 れ 、 そ の 書 式 文 字 に 対 応 す る 型 で 可 変 個 の 引 き 数 を 読 み 込 み 、 印 字 す る 。

#include <stdio.h>
#include <stdarg.h>

void
foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;

va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break; }
va_end(ap); }

こ の 文 書 に つ い て

こ の man ペ ー ジ は Linux man−pages プ ロ ジ ェ ク ト の リ リ ー ス 3.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。