【C言語】関数の引数に書けるvoidは省略したほうがいい?

C言語を学び始めたばかりの方へ、この記事では関数の引数にvoidを使うべきかどうかについて解説します。

voidの基本的な役割や使い方、メリットとデメリット、そしてvoidを省略した場合の影響について詳しく説明します。

さらに、実際のコード例を通じて、voidを使った場合と省略した場合の違いを確認できます。

この記事を読むことで、voidの使い方とその重要性を理解し、より良いコードを書くための知識を身につけることができます。

目次から探す

関数の引数におけるvoidの基本概念

voidの役割とは?

C言語におけるvoidは、関数の引数や戻り値が「何もない」ことを示すために使われます。

具体的には、以下のような役割があります。

  1. 戻り値がない関数: 関数が何も値を返さない場合にvoidを使います。

例えば、画面にメッセージを表示するだけの関数などが該当します。

  1. 引数がない関数: 関数が引数を取らない場合にvoidを使います。

これにより、関数が何も受け取らないことを明示的に示すことができます。

関数宣言と定義におけるvoidの使い方

関数の宣言と定義において、voidは以下のように使われます。

戻り値がない関数

戻り値がない関数の宣言と定義は以下のようになります。

// 関数の宣言
void printMessage(void);
// 関数の定義
void printMessage(void) {
    printf("Hello, World!\n");
}

この例では、printMessage関数は何も値を返さず、引数も取りません。

voidを使うことで、戻り値がないことと引数がないことを明示的に示しています。

引数がない関数

引数がない関数の宣言と定義は以下のようになります。

// 関数の宣言
void doNothing(void);
// 関数の定義
void doNothing(void) {
    // 何もしない
}

この例では、doNothing関数は引数を取らず、何も実行しません。

voidを使うことで、引数がないことを明示的に示しています。

引数がある関数

引数がある関数の場合、voidは使いません。

以下は引数がある関数の例です。

// 関数の宣言
int add(int a, int b);
// 関数の定義
int add(int a, int b) {
    return a + b;
}

この例では、add関数は2つの整数引数を取り、その合計を返します。

引数がある場合、voidは使わずに引数の型と名前を指定します。

以上のように、voidは関数の引数や戻り値がないことを明示的に示すために使われます。

これにより、コードの可読性が向上し、意図が明確になります。

voidを使うメリットとデメリット

メリット

コードの可読性向上

C言語において、関数の引数にvoidを明示的に書くことは、関数が引数を取らないことを明確に示すための手段です。

これにより、コードを読む他のプログラマーに対して、関数が引数を受け取らないことを明確に伝えることができます。

例えば、以下のような関数宣言があります。

void myFunction(void);

この宣言を見るだけで、myFunctionが引数を取らないことが一目でわかります。

これにより、コードの可読性が向上し、他の開発者がコードを理解しやすくなります。

コンパイラの警告を防ぐ

関数の引数にvoidを明示的に書くことで、コンパイラが引数の取り扱いに関する警告を出すのを防ぐことができます。

特に、ANSI C(C89)やC99などの標準に準拠したコンパイラでは、引数がないことを明示的に示すためにvoidを使うことが推奨されています。

以下のような関数宣言を考えてみましょう。

void myFunction();

この場合、コンパイラは引数がないことを明示的に示していないため、警告を出す可能性があります。

一方、voidを使うことで、コンパイラに対して明確に引数がないことを示すことができます。

デメリット

冗長なコードになる

関数の引数にvoidを明示的に書くことは、場合によっては冗長なコードになることがあります。

特に、コードが長くなりがちなプロジェクトでは、毎回voidを記述することが手間に感じることもあります。

以下のような関数宣言を考えてみましょう。

void myFunction(void);

このように、voidを毎回書くことが冗長に感じる場合があります。

特に、関数が多いプロジェクトでは、この冗長さが積み重なることがあります。

初心者にとっての理解の難しさ

C言語を学び始めたばかりの初心者にとって、関数の引数にvoidを使うことは少し難しく感じるかもしれません。

特に、voidの意味や役割を理解するのに時間がかかることがあります。

以下のような関数宣言を見たときに、初心者は混乱するかもしれません。

void myFunction(void);

この場合、voidが何を意味するのか、なぜ必要なのかを理解するのに時間がかかることがあります。

初心者にとっては、まず基本的な関数の使い方を理解することが優先されるため、voidの使用が混乱を招くことがあります。

以上のように、関数の引数にvoidを使うことにはメリットとデメリットがあります。

次のセクションでは、voidを省略する場合の影響について詳しく見ていきます。

voidを省略する場合の影響

省略した場合の挙動

C言語において、関数の引数にvoidを明示的に書かない場合、その関数は引数を取らないことを意味します。

しかし、voidを省略すると、コンパイラによっては異なる挙動を示すことがあります。

具体的には、関数の引数が不明確になるため、意図しない動作を引き起こす可能性があります。

例えば、以下のような関数宣言を考えてみましょう。

int myFunction();

この場合、myFunctionは引数を取らない関数として解釈されることが期待されますが、実際には引数の有無が不明確です。

これに対して、以下のようにvoidを明示的に書くことで、引数を取らないことが明確になります。

int myFunction(void);

コンパイラの対応

ANSI CとC99の違い

ANSI C(C89/C90)とC99では、関数の引数に対する扱いが異なります。

ANSI Cでは、引数リストが空の場合、voidを明示的に書かないと、関数が不特定の引数を取る可能性があると解釈されます。

これに対して、C99では、引数リストが空の場合、voidを明示的に書かなくても引数を取らない関数として解釈されます。

以下に、ANSI CとC99での違いを示します。

int myFunction(); // 不特定の引数を取る可能性がある
int myFunction(void); // 引数を取らないことが明確
int myFunction(); // 引数を取らないことが明確
int myFunction(void); // 引数を取らないことが明確

コンパイラごとの違い

コンパイラによっては、ANSI CとC99の違いを厳密にチェックするものもあれば、柔軟に対応するものもあります。

例えば、GCC(GNU Compiler Collection)やClangなどの一般的なコンパイラは、C99の標準に従って動作しますが、ANSI Cのコードもサポートしています。

以下に、GCCを使用した場合の例を示します。

#include <stdio.h>
// ANSI Cスタイルの関数宣言
int myFunction();
// C99スタイルの関数宣言
int myFunction(void);
int main() {
    printf("Hello, World!\n");
    return 0;
}
int myFunction() {
    return 42;
}

このコードをGCCでコンパイルすると、特に警告やエラーは発生しません。

しかし、ANSI Cスタイルの関数宣言は、引数の有無が不明確であるため、注意が必要です。

実際のコード例

ここでは、実際のコード例を通じて、関数の引数にvoidを使った場合と省略した場合の違いを見ていきます。

voidを使った関数宣言と定義

まずは、関数の引数にvoidを使った場合のコード例を見てみましょう。

#include <stdio.h>
// 引数にvoidを使った関数宣言
void printMessage(void);
int main(void) {
    printMessage();
    return 0;
}
// 引数にvoidを使った関数定義
void printMessage(void) {
    printf("Hello, World!\n");
}

このコードでは、printMessage関数の引数にvoidを指定しています。

これにより、この関数は引数を取らないことが明示されています。

voidを省略した関数宣言と定義

次に、関数の引数にvoidを省略した場合のコード例を見てみましょう。

#include <stdio.h>
// 引数にvoidを省略した関数宣言
void printMessage();
int main(void) {
    printMessage();
    return 0;
}
// 引数にvoidを省略した関数定義
void printMessage() {
    printf("Hello, World!\n");
}

このコードでは、printMessage関数の引数にvoidを指定していません。

C言語では、引数を省略した場合も引数を取らない関数として扱われますが、コンパイラによっては警告が出ることがあります。

それぞれのコンパイル結果

それでは、上記の2つのコードをコンパイルした結果を見てみましょう。

voidを使った場合のコンパイル結果

$ gcc void_example.c -o void_example
$ ./void_example
Hello, World!

この場合、特に警告やエラーは出ず、正常に動作します。

voidを省略した場合のコンパイル結果

$ gcc no_void_example.c -o no_void_example
no_void_example.c: In function ‘main’:
no_void_example.c:6:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
    6 | int main() {
      |     ^~~~
$ ./no_void_example
Hello, World!

この場合、コンパイラによっては「関数宣言がプロトタイプではない」という警告が出ることがありますが、プログラム自体は正常に動作します。

まとめ

関数の引数にvoidを使うかどうかは、コードの可読性やコンパイラの警告を防ぐために重要です。

特に、他の開発者と共同で作業する場合や、大規模なプロジェクトではvoidを使うことでコードの明確性が向上します。

一方で、短い関数が多い場合や、初心者にとっては冗長に感じることもあります。

最終的には、プロジェクトの方針やチームのコーディングスタイルに合わせて使い分けることが重要です。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

目次から探す