stdarg マクロ
va_list、va_start、va_arg です。
「stdarg マクロ」はCoddyKit上の無料C Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。
可変長引数関数とは
可変長引数関数は、引数の個数が可変の関数です。すでに使用した printf は、任意の個数の値を受け取れます。
C では、<stdarg.h> のマクロを使って独自の可変長引数関数を作成できます。
#include <stdio.h>
int main(void) {
printf("%d %d %d\n", 1, 2, 3);
printf("%s\n", "any count of args");
return 0;
}省略記号
可変長引数関数は、最後のパラメーターとして ...(省略記号)を指定して宣言します。
可変部分がどこから始まるのかを関数が把握できるように、その前に少なくとも 1 つの名前付きパラメーターが必要です。
#include <stdio.h>
#include <stdarg.h>
void demo(int count, ...) {
printf("This function takes %d extra args\n", count);
}
int main(void) {
demo(3, 10, 20, 30);
return 0;
}stdarg.h をインクルードする
可変長引数を読み取るには、#include <stdarg.h> が必要です。
これにより、型 va_list とマクロ va_start、va_arg、va_end が定義されます。
#include <stdio.h>
#include <stdarg.h>
void show(int n, ...) {
va_list args;
va_start(args, n);
va_end(args);
printf("set up and cleaned up\n");
}
int main(void) {
show(2, 5, 6);
return 0;
}va_list と va_start
現在の位置を追跡する va_list 変数を宣言します。次に va_start(list, last) を呼び出し、最後の名前付きパラメーターを渡します。
これにより、リストは最初の可変長引数を指すようになります。
#include <stdio.h>
#include <stdarg.h>
void first(int count, ...) {
va_list args;
va_start(args, count);
int value = va_arg(args, int);
printf("first variadic arg = %d\n", value);
va_end(args);
}
int main(void) {
first(1, 99);
return 0;
}va_arg: 値を読み取る
va_arg(list, type) は次の引数を返し、リストを進めます。読み取る正確な型を指定する必要があります。
呼び出すたびに、次の引数へ 1 つ進みます。
#include <stdio.h>
#include <stdarg.h>
void three(int n, ...) {
va_list args;
va_start(args, n);
int a = va_arg(args, int);
int b = va_arg(args, int);
int c = va_arg(args, int);
printf("%d %d %d\n", a, b, c);
va_end(args);
}
int main(void) {
three(3, 7, 8, 9);
return 0;
}va_end: 後処理
読み取りが終わったら、必ず va_end(list) を呼び出してください。プラットフォームで必要な後処理を実行します。
これを忘れると、一部のシステムでは未定義動作につながります。
#include <stdio.h>
#include <stdarg.h>
int add_two(int dummy, ...) {
va_list args;
va_start(args, dummy);
int sum = va_arg(args, int) + va_arg(args, int);
va_end(args);
return sum;
}
int main(void) {
printf("%d\n", add_two(0, 4, 6));
return 0;
}引数の個数を把握する
これらのマクロからは、いくつの引数が渡されたかを知ることはできません。個数は自分で伝える必要があります。
よく使われる方法は、sum(3, a, b, c) のように、先頭に個数のパラメーターを置くことです。
#include <stdio.h>
#include <stdarg.h>
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; i++)
total += va_arg(args, int);
va_end(args);
return total;
}
int main(void) {
printf("%d\n", sum(4, 1, 2, 3, 4));
return 0;
}番兵値を使う
終端を示す別の方法は番兵です。これは呼び出し側が含める特別な終端値で、たとえば -1 や NULL です。
番兵を読み取るまでループします。
#include <stdio.h>
#include <stdarg.h>
int sum_until_neg(int first, ...) {
va_list args;
va_start(args, first);
int total = first, v;
while ((v = va_arg(args, int)) != -1)
total += v;
va_end(args);
return total;
}
int main(void) {
printf("%d\n", sum_until_neg(10, 20, 30, -1));
return 0;
}デフォルト引数昇格
可変個引数はデフォルト引数昇格を受けます。char と short は int に、float は double になります。
そのため、va_arg では小さい整数を常に int として、浮動小数点数を double として読み取ってください。
#include <stdio.h>
#include <stdarg.h>
void show_double(int n, ...) {
va_list args;
va_start(args, n);
double d = va_arg(args, double);
printf("%.2f\n", d);
va_end(args);
}
int main(void) {
show_double(1, 3.5f);
return 0;
}va_list をコピーする
引数を2回走査する必要がある場合は、読み取る前に va_copy(dest, src) を使ってリストを複製してください。
va_end の後に va_list を再利用することはできません。再利用するには va_start で開始し直す必要があります。
#include <stdio.h>
#include <stdarg.h>
void twice(int n, ...) {
va_list a, b;
va_start(a, n);
va_copy(b, a);
printf("%d %d\n", va_arg(a, int), va_arg(b, int));
va_end(a);
va_end(b);
}
int main(void) {
twice(1, 42);
return 0;
}平均を計算する
個数を指定するパターンと浮動小数点数の読み取りを組み合わせると、可変個引数として渡された数値のリストの平均を計算できます。
#include <stdio.h>
#include <stdarg.h>
double average(int count, ...) {
va_list args;
va_start(args, count);
double sum = 0;
for (int i = 0; i < count; i++)
sum += va_arg(args, double);
va_end(args);
return sum / count;
}
int main(void) {
printf("%.2f\n", average(3, 2.0, 4.0, 6.0));
return 0;
}理解度チェック
stdarg マクロについての理解度を確認しましょう。
まとめ
可変個引数の仕組みについて学びました。
- 名前付きパラメーターを少なくとも1つ置いた後に
...を付けて宣言します。 va_start(list, last)で開始し、va_arg(list, type)で読み取り、va_end(list)で後処理を行います。- マクロは個数を把握していないため、個数のパラメーターまたは番兵を使います。
- デフォルト引数昇格に注意してください。小さい整数は
intとして、floatはdoubleとして読み取ります。
よくある質問
「stdarg マクロ」レッスンは無料ですか?
はい。「stdarg マクロ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。
「stdarg マクロ」で何を学びますか?
va_list、va_start、va_arg です。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「stdarg マクロ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC Academyレッスンでコードを書いて実行できますか?
はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- stdarg マクロ
- printf 風関数の記述
- 型安全性に関する注意点
- 実践例