C言語の関数の作り方とは?関数の定義方法がすぐわかる

5, 2020-08-06

目次

C言語における関数の作り方

今回はC言語の関数の作り方を紹介します。
C言語で関数を作るには↓のような手順を踏みます。

  • 返り値の型を決める

  • 関数名を決める

  • 引数(仮引数)を決める

  • 関数のブロックを書く

それでは関数とは何なのか?
というところから話を始めさせて頂きたいと思います。

関連記事
C言語の関数のプロトタイプ宣言の書き方
C言語のatoi関数の使い方: 文字列を整数に変換する
C言語のprintfの簡単な使い方: フォーマット文字列と引数

関数とは何なのか?

関数とは「処理のひとまとまり」のことです。
コードをたくさん書いて、処理が複雑になってきたなーと思ったら、関数にそれらの一部の処理を抜き出します。
そうすることでコードの見栄えをよくしてプログラムをスッキリさせることが可能になるわけです。

関数には引数(ひきすう)返り値(かえりち)というものがあります。
(返り値は戻り値と言うこともあります)

引数とは、関数の入力のことです。
外部から関数に入力を与えたい場合、この引数に入力を渡します。
引数は複数渡すことが可能で、それぞれの引数には名前を付けることが出来ます。

関数内ではその名前を付けた引数を使って処理を書きます。
引数にはintdouble, ポインタや構造体や文字列などを渡すことが出来ます。
これらが関数への入力になるわけです。

いっぽう返り値とは、関数の出力のことです。
関数からなにか値を、関数の呼び出し側に返したい時があります。
関数内でいろいろ処理をして、その処理の結果を値として関数の呼び出し側に返す時に使うのが返り値です。

返り値にもintdouble, ポインタや構造体や文字列などを指定することが出来ます。

関数の使い方は色々ありますが、その基本となるのが引数と返り値を使った使い方です。
関数に引数で入力を与えて、関数内でいろいろな処理をして、返り値として関数からその結果を得る。
というのが関数のいちばん「らしい」使い方です。

もちろん引数が無かったり、返り値が無かったりする関数も作ることが出来ます。
それらの関数も関数の内部ではいろいろな処理をします。

関数の構造

関数は↓のような構造になっています。

返り値の型 関数名(引数リスト) {
    関数の内容
}

実際のコードは↓のようになります。

int func(void) {
    return 0;
}

まずは「返り値の型」から具体的に見てみたいと思います。

返り値の型を決める

返り値」とは、関数から返ってくる値のことです。
C言語なので、値にはがあります。
関数を作る時はこの「返り値の型」を決めておく必要があります。
関数を作る時は、その関数が何を返すのか? というところを最初に考えると良いかもしれません。
もちろん関数名や引数、処理内容から考えてもいいですが。

たとえばint型の整数を返す関数を定義したい場合は、↓のように関数名の前にを書きます。

int func(void) {
    return 0;
}

funcというのが関数の関数名ですが、その関数名の前に書かれているintが、その関数の型になります。
関数名の次に出てくる(void)はこの関数が引数を持っていないことを表しています。
例えば返り値の型をdoubleにしたい場合は、↓のようにします。

double func(void) {
    return 0.0;
}

voidというキーワードを型に使うことで、返り値を返さない関数を作ることが出来ます。
voidを書くとその関数は「返り値が無いよ」という意味になります。

void func(void) {
}

返り値の型のところにvoidと書かれた関数は返り値を返さないので、returnを書かなくてもエラーになりません。

型には構造体も使えます。
例えばstruct animalという構造体を、関数の返り値の型にしたい場合は↓のようにします。

struct animal {
    int age;
};

struct animal func(void) {
    struct animal a = {0};
    return a;
}

return文で返り値を返す

returnを書くと、その行で関数は終了し、return文に書かれている値または変数を、関数の呼び出し側に返します。
たとえば、int型の返り値を返す関数funcから整数0を返すようにしたい場合は↓のように書きます。

int func(void) {
    return 0;
}

int main(void) {
    int a = func();
    printf("%d\n", a);
}

↑の場合、関数を呼び出している側のmain関数内の変数aには、値0が代入されます。
よって出力結果は↓のようになります。

0

return文は値のコピーを関数の呼び出し側に返します。
なので↑の例では変数の値のコピーが呼び出し側に返されます。
引数に値を渡している時も、返り値を返している時も、このコピーが発生しているということは頭の片隅に置いておいてください。

関連記事
C言語の関数で戻り値を返す方法【return文】

関数名を決める

関数名とは、「関数の名前」のことです。
この関数名は、作った関数を呼び出したい時などに使われます。
関数を作る時にこの関数名を書いておかないと、コンパイルエラーになります。

↓のコードの場合、funcというのが関数名です。

void func(void) {
}

関数名には_(アンダーバー)や大小英数字が使えます。

void this_is_func_123(void) {
}

void thisIsFunc123(void) {
}

void _this_isFunc_123(void) {
}

ただし数字は関数名の先頭には使えません。
例えば↓のような関数名はエラーになります。

void 123func(void) {
}

引数(仮引数)を決める

関数というのは、「ある値を関数に渡して」計算させて、その結果を返り値として受け取る、という仕事をするのが一般的です。
その関数に渡す「ある値」のことを「引数(ひきすう)」と言います。

関数に引数を作るには、関数名の後にカッコ(())を付けて、その中に変数のように型と変数名を書きます。
たとえばint aという引数を、関数funcに作る場合は↓のようにします。

void func(int a) {
}

複数の引数を作りたい場合はカンマ(,)で引数を区切ります。
たとえばint aint bという引数を関数funcに作りたい場合は↓のようにします。

void func(int a, int b) {
}

これらの引数、特に関数の定義側に書かれている引数は正確には「仮引数(かりひきすう)」と言いますが、引数と言っている人も多いので、参考程度に覚えておきましょう。

これらの引数は、変数を宣言したことと同じです。
ですので、関数内で使うことが出来ます。

void func(int a, int b) {
    int c = a * b;
}

voidキーワードを使うことで、引数が無い関数を作ることが出来ます。
カッコの中にvoidを書くと、その関数には引数が存在しないことになります。

void func(void) {
}
(^ _ ^)

関数なのに返り値も引数もないのは不思議だね

(・ v ・)

でもよく使われるよ

関連記事
C言語の関数の引数が多くなった時の対処方法【引数爆発】

関数に引数(実引数)を渡すには?

さきほど作った関数を呼び出して、実際に引数に値を渡したいときは、カッコ(())の中に値を書いて関数を呼び出します。

void func(int a, int b) {
    printf("a = %d, b = %d\n", a, b);
}

int main(void) {
    func(1, 2);
    return 0;
}

↑のfunc関数の呼び出し(main関数内のfunc(1, 2)の部分)では値1int aに渡されて、値2int bに渡されます。
つまりfunc関数のprintfの出力は↓のようになります。

a = 1, b = 2

この関数呼び出し側の引数(1, 2のこと)のことを正確には「実引数(じつひきすう)」と言います。
ですが例によって引数と言っている人も多いので、参考程度に覚えておきましょう。

関数のブロックを書く

ブロックとは{}の波カッコのことを言います。
関数に付いている波カッコのことを「関数のブロック」、または「関数の内容」と言います。

ブロック内には、関数にやらせたい仕事を書きます。
例えば引数aと引数bを足し算した結果を、返り値として返したい場合は↓のようにします。

int func(int a, int b) {
    return a + b;
}

この関数funcfunc(1, 2)のようにして呼び出した場合、関数funcの返り値はabを足した結果になります。
ブロックの中にはfor文やif文など、ありとあらゆる命令を書くことが出来ます。

int func(int a, int b) {
    int n = 0;

    for (int i = a; i < b; i++) {
        n += i;
    }

    return n;
}

関数の使い道は?

このように定義した関数の使い道はなにがあるのでしょうか?
すでに解説したように関数とは「処理のひとまとまり」です。

つまり関数は複数の処理をまとめる力を持っています。
コードを書いていてコードが長くなって「なんか見づらいなぁ」となったら。
そういう時はコードを関数にまとめるとコードが綺麗になるかもしれません。

  • 関数はコードを綺麗にする場合がある

また関数を使うことでコードを抽象化することもできます。
この抽象化というのはうまく使うと開発の効率を大幅に上げることができます。

詳細なコードを抽象的にして1つの関数として抽出する、という芸当が出来るようになればもはや初心者ではないです。
これはプロでも上手くできるときと出来ない時があるので中々悩ましい問題です。
要は抽象化というのはけっこう難しいということですね。

関数の作り方を覚えたらぜひコードの抽象化にもチャレンジしてみてください。

関連記事
C言語の関数の特殊化
C言語の関数の引数が多くなった時の対処方法【引数爆発】

関数の定義例

関数の定義例です。
↓は0からnまでの合計を得る関数です。

#include <stdio.h>

/**
 * 1からnまでの和を計算する関数。
 * 
 * @param {int} n 
 * @return {int} 和 
 */
int get_sum(int n) {
    int sum = 0;

    for (int i = 1; i <= n; i++) {
        sum += i;
    }

    return sum;
}

int main(void) {
    int sum = get_sum(100);

    printf("%d\n", sum);  // 5050

    return 0;
}

関数を定義できるようになるとこのように自分で便利な関数を作成することができます。
関数をいくつも作ってそれをストックしておけばそれは自作ライブラリです。
自作ライブラリは家宝にするかGitHubで公開するか選べますが、公開したら他の人が喜ぶでしょう。

関数を作って処理を切り分ける

まとめです。
関数は↓のようにして作ります。

  • 返り値の型を決める

  • 関数名を決める

  • 引数(仮引数)を決める

  • 関数のブロックを書く

関数を使うと、複雑な処理をシンプルに切り分けることが出来るようになります。
ぜひ関数を作れるようになって、プログラミングをもっと楽しいものにしましょう。



この記事のアンケートを送信する