Skip to content

Instantly share code, notes, and snippets.

@n01e0
Last active August 16, 2019 04:22
Show Gist options
  • Save n01e0/dd8b95a2cf1cd461d466031386df1bc2 to your computer and use it in GitHub Desktop.
Save n01e0/dd8b95a2cf1cd461d466031386df1bc2 to your computer and use it in GitHub Desktop.
C言語で可変引数を受け取る

C言語で可変引数を受け取る

agenda

可変引数とは

ご存知の方もいるかもしれないがC言語には可変引数という概念がある。

一般的なC言語での関数の宣言は

int sum(int a, int b);

みたいな感じだろう。

関数定義の際に必要なのは

戻り値の型 関数名 仮引数の型 仮引数名

となる。ここで仮引数は必要な数だけ定義し、関数呼び出しの際にも、定義した型、数の実引数を渡す。


疑問

しかし、普段からよく使うあのprintf()関数はどうなっているだろう。

様々な型の、様々な数の引数を渡しても正しく動作する。

これはprintf()関数を前述の感覚で捉えていると違和感を覚える。

様々な型の、不特定数の引数を受け取れるようにするのが

可変引数

という仕組みだ

身近な可変引数

可変引数を用いた関数定義はprintf()を例に取ると

int printf(const char *format, ...);

となる。

この...の部分が可変引数の実体である。

使い方

可変引数を用いる為の関数等はstdarg.hで定義されている。

基本的な例は

#include <stdarg.h>
void (int last, ...){
    va_list ap;
    va_start(ap, last);
    int arg[last];
    for(int i; i < last; i++){
        arg[last] = va_arg(ap, int);
    }
    va_end(ap);
}

みたいな感じだ。

stdarg.h

va_list

受け取った複数の引数を一つにまとめる構造体。

va_start

va_start(va_list ap, last);

last(引数郡の最初の変数)とapを受け取り、last以後の引数をapに格納する。

初期化処理だと思って良い。

va_arg

型を指定しapから順番に引数を取り出す。

va_end

apをクリアする。

これらを上手く組み合わせることで、可変引数を受け取る関数を作れる。

以下は数値とその個数を与えると平均が帰ってくる関数

#include <stdarg.h>

float avg(int amnt, ...){
    va_list list;
    va_start(list, amnt);
    
    float sum = 0;
    for(int i = 0; i < amnt; i++){
        sum += va_arg(list, int);
    }

    va_end(list);

    return sum/amnt;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment