ユーニックス総合研究所

  • home
  • archives
  • c-func-args

C言語の関数の引数の使い方

  • 作成日: 2021-10-28
  • 更新日: 2024-03-15
  • カテゴリ: C言語

C言語の関数の引数の使い方

C言語には関数があります。
この関数は引数を取ることが可能です。

関数は外部から入力を貰う時にこの引数を使って入力を受け取ります。
そのため関数の引数を使えないと、関数に入力を与えられません
(グローバル変数を使う場合は除きます)

関数の引数はたとえばintfloat, その他にもdoubleといった型を指定することができます。
さまざまなC言語の型を指定することで、いろいろなデータを関数に渡すことかできます

このようにC言語の関数は引数を取ることができます。
この記事ではC言語の関数の引数の使い方を具体的に解説します。
具体的なコードを早く見たい方は↓までジャンプしてください。

関数の引数の使い方

C言語や他の言語を扱うYoutubeも公開しています。
興味がある方は以下のリンクからご覧ください。

Youtubeの当チャンネル

関連記事
C言語の関数の作り方とは?処理をわけてプログラムをスッキリさせる

「引数」の読み方は?

引数とは「ひきすう」と読みます。
いんすうとは読まないので注意が必要です。
引数は英語で言うと「argument(アーギュメント)」や「parameter(パラメーター)」という意味になります。

関数の引数とはなにか?

関数の引数は数学やプログラミングにおける関数において、関数が外部から入力を得たい場合に指定されます。
つまり関数を使う人は、引数を指定することで関数に入力を与えることができることになります。

たとえば関数func()があったとします。
この関数を呼び出す時に123223という値をfunc()の引数に指定したいとします。
そういった場合は↓のように書くことが出来ます。

func(123, 223)  

func()は呼び出される時に引数に123223を指定されています。
func()は内部で処理を実行するときに、これらの引数を参照することが出来ます

このように関数の引数は関数に外部から入力を与えたい時に指定します。
このような仕組みを用意することで関数の使い勝手がよくなり、プログラムの柔軟性が上がるわけですね。

関数の引数を使うメリット・デメリットは?

C言語の関数の引数を使うメリットはなんでしょうか?
引数を使うメリットは、関数の外部から関数の内部に値を注入できるという点です。

このメリットによって関数のふるまいを外部から変更することができます。
関数は内部で引数の値をチェックして、その値に応じて動作を変えます。

関数に外部から値を注入できるのが引数のメリット!

では引数のデメリットとはなんでしょうか?
引数を使うデメリットは、引数の数が多いと関数が不格好な関数になってしまう点です。
引数の数がたくさん増えてしまうことを引数爆発と言ったりもします。

引数爆発を起こした関数は非常に使い勝手が悪くなります
そのため開発者から嫌われてあまり使われなくなるなど、[uy]悲運な運命をたどります[/uy]。
そうならないようにするには、関数に処理させるタスクの量を調整し、関数を適切に分割する必要があります。

関数の引数の書き方

C言語の関数の引数の書き方を見てみます。
C言語の関数の引数は↓のように書きます。

返り値の型 関数名 ( 引数の型 引数名, 引数の型 引数名, ... ) {  
    関数の処理  
}  

↑のように関数名のあとのカッコの中に引数のリストを書きます。
引数のリストの各要素は、引数の型と引数名に分かれています。
また各要素はカンマ(,)で区切られます。

「引数の型」にはC言語に存在する型を指定することができます。
intfloat, doubleやポインタ型など、あらゆる型を指定できます。

引数名には半角英数字とアンダーバー(_)を含む文字を指定することが出来ます。
ただし最初の1文字目は数字は指定できません
つまり↓のような引数名はOKです。

arg  
arg_123  
Arg123  
_123_arg  

関数の引数渡しの挙動(コピーか参照か)

C言語の関数の引数は関数に引数を渡す時どのような挙動になるのでしょうか?
結論から言うと、C言語の関数の引数はすべて値渡しになります。
int型やfloat型ももちろんポインタ型も値渡しになります。

ポインタ型の場合はポインタの引数にポインタを渡すことを「ポインタ渡し」とか「参照渡し」と言ったりもします。
しかしC言語では基本的に引数の値の渡しはすべて値渡しになります。
ポインタの場合はポインタの持つアドレスが値渡しになっているという感じです。

C言語の規格書の「6.5.2.2 関数呼出し」にはこのように書かれています。

関数呼出しの準備の段階で,実引数を評価し,各実引数の値を対応する仮引数に代入する

実引数とは関数呼び出し側の引数のことで、仮引数とは関数宣言側の引数のことを言います。
つまり関数の引数渡しは実際には「代入」で実現されているのがわかります。

代入については「6.5.16 代入演算子」に書かれています。

代入演算子は,左オペランドで指し示されるオブジェクトに値を格納する。 ...

「値を格納」というのはつまりコピーということになります。
このように関数の引数渡しは値渡しで行われているのがわかります。

関数の引数の使い方

それでは具体的なコードを通してC言語の関数の引数の使い方を見てみたいと思います。

引数を取らない関数

まず基本となるのが引数を取らない関数です。
C言語では引数が存在しないことを表すにはvoidを使います。

void func0(void) {  
    // ここに色々な処理  
}  

↑の場合、関数func0は引数を取らない関数になります。
そのため外部から引数を使って入力を与えることはできません

この関数は↓のように呼び出すことができます。

    func0();  

1つの引数を取る関数

引数を1つだけ取る関数は↓のように作ります。

void func1(int arg1) {  
    // ここに色々な処理  
}  

↑の場合、関数func1int型の引数arg11つだけ取る関数です。
このint型の引数arg1は関数内で参照することができます。

関数funcは↓のように呼び出すことができます。

    func1(123);  

2つの引数を取る関数

引数を2つ取る関数は↓のように作ります。

void func2(int arg1, float arg2) {  
    // ここに色々な処理  
}  

↑の場合、funcs3()は引数arg1arg2を取る関数です。
引数はカンマ(,)で区切られてカッコの中に並べられています。

このように関数の引数にはいろいろな型の引数を設定することが出来ます
↑の例ですとintfloatを並べていますが、もちろんdoublelongなども指定できます。

この関数func2()は↓のように呼び出すことができます。

    func2(123, 3.21);  

文字列を引数に取る関数

文字列を引数に取る関数は↓のように作ります。

void funcstr(const char *str) {  
    // ここに色々な処理  
}  

↑の場合、const char *型の引数strを関数に設定しています。
C言語の文字列はconst char *に代入することが可能なので、↑の関数は↓のように呼び出すことができます。

    funcstr("Hello, World!");  

配列を引数に取る関数

配列を引数に取る関数は↓のように作ります。

void funcarray(int ary[]) {  
    // ここに色々な処理  
}  

↑の関数funcarray()int型の配列を引数に取る関数です。
↓のように呼び出すことが出来ます。

    int ary[] = {1, 2, 3};  
    funcarray(ary);  

関数の引数におけるint ary[]という表記は、実際にはint *aryと等しい表記です。
funcarray()内でこの引数arysizeof演算子で参照すると、ary配列全体のサイズではなく、ポインタのサイズが求まるので注意が必要です。

🦝 < 配列の表記なのにポインタのサイズが求まる

🐭 < C言語のワナ

関連記事
C言語で関数に配列を渡す方法

ポインタを引数に取る関数

ポインタを引数に取る関数は↓のようにつくります。

void funcptr(int *ptr) {  
    // ここに色々な処理  
}  

↑の関数funcptr()intのポインタ型の変数ptrを取る関数です。
この関数にはint型のポインタを渡せます。
たとえば↓のようにです。

    int i = 0;  
    funcptr(&i);  

関数の引数にポインタを使うと、関数内の処理でポインタの指す値を変更することができます
つまり関数の処理の結果を引数に渡したポインタに保存することが可能になります。
C言語ではこのような設計は非常によく使われます。
例を挙げるとC標準ライブラリのfopen()系の関数などがそうです。

関連記事
C言語で関数の引数にポインタを渡す【ポインタの値渡し】
C言語の関数ポインタを引数に渡す方法

可変長引数を取る関数

可変長引数を取る関数を作りたい場合は↓のようにします。

void print(const char *fmt, ...) {  
    va_list ap;  
    va_start(ap, fmt);  
    vprintf(fmt, ap);  
    va_end(ap);  
}  

↑の例では可変長引数「...」を関数print()の引数リストに設定しています。
このようにすると可変長引数を取る関数を作ることができます。

この関数print()は↓のように呼び出せます。

    print("Hello, %s!\n", "World");  
    // Hello, World!  

C言語で可変長引数を扱いたい場合はこのようにva_で始まる関数を使います。
これらはstdarg.hで宣言されている関数です。

おわりに

今回はC言語の関数の引数の使い方について見てみました。
関数の引数を扱えるようになると関数に入力を渡すことができます。
関数の振る舞いを外側から変えることでさらに柔軟な設計が可能になります。

🦝 < 引数で振る舞いを変えよう

🐭 < 刺激的な引数、求む