記事には広告を含む場合があります。

C言語入門講座

【C言語】関数をわかりやすく解説!引数・戻り値とは?呼び出し方は?

2024年10月27日

おゆ

組み込み系プログラマとして5年働いていた元エンジニアです。得意言語はC言語とC++。本サイトでは学生および新人組み込み系プログラマに向けてプログラミング知識をわかりやすく解説しています。

C言語、C++は関数なしでは成り立ちません。

関数を作ることで作業を効率化できますし、コードの修正も容易になります。

この記事では関数の基本的な使い方をわかりやすく解説します。

関数とは何か、なぜ必要かをわかりやすく解説

プログラミングでいう関数は数学の関数とは別のものです。

プログラミングにおいての関数とは何か値を渡すと処理をしてできた値を返してくれるものです。

例えば1, 2という2つの値を渡すと足して3という値を返す足し算の関数を作ることもできます。

1と2を渡すと引き算をして答えを返してくれる関数も作れます。

関数

もちろん、もっと複雑なことをする関数も作れますよ!

関数がどんなものかなんとなくわかったけど、なんで関数が必要なの?関数を使わずに足し算や引き算のコードをそのまま書けばよくない?
おゆ
確かに関数に分けなくてもコードは書けます。短い処理や1度しかやらない処理ならそのまま書くでOKです。でも複雑な処理を何度も行うコードでは関数があると便利です。

例えば以下のコードでは最大公約数を3回求めています。

同じ処理が何度も書いてあることでコードが長く、見にくくなってしまっています。

例:

#include <stdio.h>
void main()
{
    int r, x, y, gcd;
    x=15;
    y=6;
    //xとyの最大公約数を計算-------
    while((r = x % y) != 0)
    {
        x = y;
        y = r;
    }
    gcd=y;
    //----------------------------
    printf("15と6の最大公約数は%d\n", gcd);

    x=15;
    y=57;
    //xとyの最大公約数を計算-------
    while((r = x % y) != 0)
    {
        x = y;
        y = r;
    }
    gcd=y;
    //----------------------------
    printf("15と57の最大公約数は%d\n", gcd);

    x=230;
    y=759;
    //xとyの最大公約数を計算-------
    while((r = x % y) != 0)
    {
        x = y;
        y = r;
    }
    gcd=y;
    //----------------------------
    printf("654と235の最大公約数は%d\n", gcd);
}

実行結果

15と6の最大公約数は3
15と57の最大公約数は3
230と759の最大公約数は23

※最大公約数の求め方はC言語例文集を一部引用

しかも最大公約数を求める部分に修正を施す場合、3か所のコードを書き替える必要があります。

一方で関数を使うと以下のようにすっきりしたコードが書けます。

おゆ
関数の使い方は下で詳しく解説するのでここでは雰囲気だけ掴んでもらえればOKです。

例:

#include <stdio.h>
int gcd(int x, int y) //最大公約数を求める関数
{
    int r;
    while((r = x % y) != 0)
    {
        x = y;
        y = r;
    }
    return y;
}
void main()
{
    int num;
    num=gcd(15,6);
    printf("15と6の最大公約数は%d\n", num);
    num=gcd(15,57);
    printf("15と57の最大公約数は%d\n", num);
    num=gcd(230,759);
    printf("230と759の最大公約数は%d\n", num);
}

実行結果

15と6の最大公約数は3
15と57の最大公約数は3
230と759の最大公約数は23

参考【ソースコード・ターミナル】VSCodeの文字化け解消方法まとめ

Visual Studio Codeで日本語のファイルを開くと文字化けする。プログラムの実行結果も日本語だけ文字化けする。どうにかならないかな… こんなお悩みにお答えします。 記事の内容 Visual ...

続きを見る

最大公約数を求めるコードを修正する場合は関数部分だけを修正すればよく、修正漏れが起こりにくいです。

関数の使い方・戻り値をわかりやすく解説

以下では簡単な例として足し算をする関数を作ってみます。

プログラム上で足し算をするには以下の材料が必要ですよね。

  • 足し算したい数字を入れる変数
  • 足し算の結果を入れる変数
  • 足し算の処理

今回は関数を作るので以下も使います。

  • 関数の名前
  • 結果の受け渡し(結果を次の処理に使うため)

これらを使って足し算をする関数は以下のように書けます。
足し算関数

関数名はplusにしました。

足し算したいデータは変数x, yとして関数名の横のカッコ内に書きます。

足し算結果のデータ型は関数名の前に書いておきます。

処理は中カッコ{ }内に書き、足し算の結果は変数resultに代入しておきます。

returnの後ろに書いた値(この場合はresult)は関数を呼び出した結果として渡されます。

関数の呼び出しについては次の項目で紹介します。

関数を作ることは関数を定義するといいます。

おゆ
なかなか複雑に見えるかもしれませんが、繰り返し使って行くうちに自然と覚えられます。

関数の使い方を一般化して書くと以下のようになります。

関数の使い方

戻り値の型 関数名(引数1, 引数2,...)
{
    処理
    return 戻り値;
}

引数とは関数に渡すデータのことです。

戻り値とは関数内での処理(計算)結果のことです。

戻り値の型には変数宣言時と同じようにintやcharなどが使えます。

戻り値を返すにはreturnの後ろに戻り値を書きます。

return以降に書いた処理は実行されません。

関数の呼び出し方

関数の呼び出し方

関数名(引数1, 引数2,...);

関数を呼び出す際には処理してほしい値を引数として渡します。

試しに上で解説したplus関数を呼び出してみます。

例:

#include <stdio.h>
int plus(int x, int y) //関数の定義
{
    int result;
    result=x+y;
    return result; //result(足した結果)が戻り値
}
void main()
{
    int num; //plus関数の戻り値と同じデータ型
    num=plus(2,3); //引数として2と3を渡して関数を呼び出し、numに戻り値5を格納
    printf("num=%d\n",num);
}

実行結果

num=5

plus関数内では引数の値を足してresultという変数に入れ、resultを戻り値にしています。

2と3を引数にしてplus関数を呼び出すにはplus(2,3)と書きます。

すると5という戻り値が返ってきます。

つまりplus(2,3)は5に置き換えられます。

その結果、numには5が代入されます。

おゆ
ちゃんと2+3=5という結果が得られました!

関数呼び出しの注意点

  • 引数と関数呼び出し時に渡す値の型と数は一致させる
  • 戻り値と戻り値を代入する変数の型は一致させる
  • 関数の定義は関数を呼び出す前に書く

上の例ではplus関数の引数x, yの型と実際に渡している値2, 5の型がどちらもint型で一致しているので正しく動作します。

関数呼び出し時にplus('A',5)のようにint型でない値を渡すとコンパイルエラーになります。

またplus関数の戻り値の型と変数numの型はどちらもintで一致させています。

これらの型も一致させないとエラーが出ます。

関数の定義は必ず関数を呼び出す前に終わらせておきます。

以下のように関数の定義前に呼び出すとコンパイルエラーになります。

例:

#include <stdio.h>
void main()
{
    int num;
    num=plus(2,3); //関数の定義の前に呼び出しているのでエラーが出る
    printf("num=%d\n",num);
}
int plus(int x, int y) //関数の定義
{
    int result;
    result=x+y;
    return result;
}

エラー文
関数未定義のエラー文

関数の定義はちゃんと書かれてるのに何でエラーになってるの?
おゆ
コンパイラはコードを上から順番に一句一句読んでいきます。関数の呼び出し部分を読んだ時点ではまだ関数の定義があることを知らないので、「関数が定義されていないのに呼び出そうとしてる!」と判断し、エラーを出してコンパイルをやめてしまうんです。

エラーが出ないようにするにはひとつ前の例のように関数の定義を事前に書いておく必要があります。

関数の定義は後半に書きたい場合の対処法は下で解説しています。

戻り値がない関数

上で紹介してきた関数はreturnで戻り値を返す関数です。

これとは別に戻り値を返さない関数もあります。

戻り値がない関数は戻り値の型がvoidで、return文は不要です。

おゆ
voidとは英語で空っぽという意味です。

下の例ではnumに格納した数字を画面上に表示する関数helloを定義しています。

hello関数には戻り値が不要なので戻り値の型はvoidで、return文は書きません。

例:

#include <stdio.h>
void hello(int num) //戻り値なしの関数
{
    printf("num=%d\n",num);
}
void main()
{
    hello(10);
}

実行結果

num=10

voidは省略できますが、書いておくとコードが見やすくなります。

引数がない関数

引数を渡す必要が無い場合は引数の位置にvoidと書きます。

下の例では引数も戻り値も無い関数helloを定義しています。

例:

#include <stdio.h>
void hello(void) //引数なしの関数
{
    printf("Hello\n");
}
void main()
{
    hello();
}

実行結果

Hello

voidを書かなくても動作には問題ありませんが、その場合呼び出し側で間違えて引数を渡してしまってもエラーになりません。

voidと書いておけばエラーになって間違えを見つけやすくなるので、書いておくのがいいです。

main関数

もうお気づきかもしれませんが、実はいつもコードに書いている「void main(){ }」という記述も関数を定義しています。

これをmain関数といいます。

戻り値の型と引数はvoidなので省略されています。

プログラマがmain関数に誤って引数を渡す心配はないので、引数のvoidは省略しています。main関数の戻り値の型は省略できません。

C言語とC++のコードにはmain関数が必須です。

プログラム実行時にはmain関数に書かれたコードが実行されるようになっています。

おゆ
main関数がないとどの関数がプログラムの本体かわからなくなってコンパイルエラーになります。

関数のプロトタイプ宣言

関数が増えてくると関数を定義するコードの量が膨大になり、main関数が後ろに追いやられてしまいます。

しかしいきなり関数のコードを読んでも何がしたいのかよくわかりません。

まずはmain関数から読みたいですよね。

でも関数の定義をmain関数の後ろに書くとコンパイルエラーになるし…

そういう時に使えるのが関数のプロトタイプ宣言です。

以下のようにプロトタイプ宣言をコードの前半に書くと関数の定義は関数呼び出しの後ろに書けます。

プロトタイプ宣言の使い方

戻り値の型 変数名(引数);

関数の定義の先頭部分をコピペし、セミコロンを付ければ完成です。

例:

#include <stdio.h>
void hello(void); //プロトタイプ宣言
void main()
{
    hello(); //関数呼び出し
}
void hello(void) //関数の定義
{
    printf("Hello\n");
}

実行結果

Hello

複数の関数を使う際にはプロトタイプ宣言を最初にまとめて書いておき、関数の定義をすべてmain関数の後ろに書くとコードが見やすくなります。

まとめ

コードをコピペしたくなったら関数を作ってみてください。

複雑な処理を関数化することでコードがすっきりしますし、修正が簡単になりますよ。

C言語で行き詰まったら…

C言語・C++がわからない時に質問できるサイト・サービス5選

C言語を独学で勉強しているけど内容がイマイチわからない。もはや何がわからないのかもわからない。 C++のエラーが解決できない。ググってもわからない。わかる人に解説してほしい。 こんなお悩みにお答えしま ...

続きを見る

ブログランキング参加中。クリックしてもらえると励みになります。

ブログランキング・にほんブログ村へ

-C言語入門講座