C言語の学習や開発を進めている中で、コンパイル時に「error: void value not ignored as it ought to be」というメッセージが表示され、戸惑った経験を持つ方は少なくありません。
このエラーは、文字通り「無視されるべきvoid型の値が、無視されずに使用されている」ことを警告しており、プログラムの型定義に関する基本的なミスが原因で発生します。
C言語は型に対して厳密な言語であるため、戻り値が存在しない関数をどのように扱うかというルールを正しく理解しておく必要があります。
本記事では、このエラーが発生する具体的なメカニズムから、よくある発生パターン、そして効率的な解決策について詳しく解説します。
エラーメッセージ「void value not ignored as it ought to be」の意味
このエラーメッセージを直訳すると、「void型の値は、当然そうあるべきであるように無視されませんでした」という意味になります。
C言語における「void型」とは、戻り値を持たない関数を定義する際に使用される特別な型です。
関数がvoidとして定義されている場合、その関数は呼び出し元に値を返さないため、計算式や代入操作に利用することはできません。
しかし、プログラマが誤ってその関数の戻り値を利用しようとした場合、コンパイラは「返す値がないはずなのに、それを使おうとしている」と判断し、このエラーを発生させます。
つまり、このエラーはプログラムの論理的な構造と、関数の型定義が矛盾していることを示しているのです。
主な発生原因と具体的なコード例
このエラーが発生する原因はいくつか考えられますが、そのほとんどは関数の戻り値に対する誤解や、プロトタイプ宣言の不備に起因します。
1. 戻り値のない関数を変数に代入している
最も典型的な原因は、戻り値がvoidである関数を呼び出し、その結果を変数に代入しようとすることです。
以下のサンプルコードを見てみましょう。
#include <stdio.h>
// 戻り値がないvoid型の関数
void displayMessage() {
printf("Hello, World!\n");
}
int main() {
int result;
// void型の関数の戻り値を変数に代入しようとしている
result = displayMessage();
return 0;
}
このコードをコンパイルすると、result = displayMessage();の行でエラーが発生します。
displayMessage関数は何も返さないため、int型の変数resultに格納するべき「値」が存在しないからです。
2. 条件式や引数の中で関数を呼び出している
関数の戻り値を直接変数に代入していなくても、条件分岐(if文)や他の関数の引数としてvoid関数を使用した場合も同様のエラーになります。
#include <stdio.h>
void checkStatus() {
// 内部的な処理のみを行う
}
int main() {
// if文の条件としてvoid型の関数を使用
if (checkStatus()) {
printf("Success\n");
}
return 0;
}
if文は、条件式の結果が「真(0以外)」か「偽(0)」かを判定するために値を必要とします。
しかし、checkStatus関数は値を返さないため、判定の材料がなくなり、コンパイラは処理を中断します。
3. 関数宣言(プロトタイプ宣言)の不足や誤り
関数自体の定義は正しく戻り値を返していても、呼び出し側がその情報を正しく認識していない場合にエラーが発生することがあります。
例えば、関数の定義がmain関数より後ろにあり、かつプロトタイプ宣言を忘れている場合です。
古いC言語の仕様では、宣言のない関数はデフォルトでint型を返すとみなされることがありましたが、現在の標準的なコンパイラでは、不一致が起きると厳格にエラーを出力します。
また、ヘッダーファイルでvoidとして宣言されているにもかかわらず、実装ファイルで値を返そうとしたり、その逆のパターンもエラーの引き金となります。
エラーを解決するためのステップ
このエラーを解消するためには、プログラムの設計を見直し、関数の役割を再定義する必要があります。
関数の戻り値型を確認する
まずは、エラーが発生している箇所で使用されている関数の定義を確認してください。
もしその関数がvoid funcName()のように定義されているのであれば、その関数から値を受け取ることはできません。
値を返して利用したいのであれば、voidをintやdouble、あるいは構造体などの適切な型に変更する必要があります。
代入や評価を行わないように修正する
関数の役割が「単なる処理の実行(画面出力やデータの更新など)」であり、値を返す必要がない場合は、呼び出し側のコードを修正します。
変数への代入を止め、単独の文として関数を呼び出すように書き換えてください。
// 修正前
// result = doSomething();
// 修正後(単独で呼び出す)
doSomething();
これにより、「戻り値を無視する」という正しい振る舞いになり、エラーは消滅します。
標準ライブラリ関数の仕様を確認する
自作関数ではなく、標準ライブラリや外部ライブラリの関数でこのエラーが出る場合は、公式ドキュメント(Manページなど)を参照してください。
例えば、printf関数は出力した文字数をint型として返しますが、中には戻り値がvoidに設定されているライブラリ関数も存在します。
「この関数は値を返すはずだ」という思い込みを捨て、正確な定義を確認することが重要です。
実践的な修正例:計算結果を取得する場合
具体的な修正のビフォー・アフターを確認しましょう。
以下は、2つの数値の和を求めるプログラムでエラーが発生し、それを修正した例です。
誤ったコード(エラー発生)
#include <stdio.h>
// void型なので値を返せない
void add(int a, int b) {
int sum = a + b;
}
int main() {
int total;
// エラー:void型の値は無視されるべきです
total = add(10, 20);
printf("合計: %d\n", total);
return 0;
}
正しいコード(修正後)
#include <stdio.h>
// 戻り値の型をintに変更
int add(int a, int b) {
int sum = a + b;
// return文を追加して値を返す
return sum;
}
int main() {
int total;
// 正しくint型の値を受け取れる
total = add(10, 20);
printf("合計: %d\n", total);
return 0;
}
合計: 30
このように、「関数が何をすべきか」に合わせて型を一致させることが、C言語プログラミングにおける鉄則です。
デバッグ時に意識すべきポイント
「void value not ignored as it ought to be」というエラーに直面したとき、デバッグの効率を上げるための視点をいくつか紹介します。
マクロ定義の確認
関数呼び出しのように見えるものが、実はマクロ(#define)で定義されている場合があります。
マクロの中で(void)0のように展開されるコードが含まれていると、予期せぬ場所でこのエラーが発生することがあります。
プリプロセッサによる展開後のコードを意識し、複雑なマクロを使用している場合はその定義を疑ってみてください。
ポインタとアドレスの取り違え
関数がvoid*(ボイドポインタ)を返す場合、これは特定の型を指さないアドレスを返しているため、エラーにはなりません。
しかし、void(型なし)とvoid*(汎用ポインタ)を混同すると、コードの意図が崩れます。
アスタリスクの有無ひとつでコンパイラの解釈は大きく変わるため、ポインタを扱う際は特に慎重に型をチェックしましょう。
警告レベルを上げて未然に防ぐ
GCCなどのコンパイラを使用している場合、-Wallや-Wextraといったオプションを付けてコンパイルすることをお勧めします。
これにより、エラーになる前の段階で「戻り値があるはずの関数でreturn文がない」といった潜在的な問題を警告(Warning)として指摘してくれます。
早期に問題を発見することで、今回のようなエラーに悩まされる時間を短縮できます。
まとめ
C言語における「error: void value not ignored as it ought to be」は、プログラムの型整合性が崩れていることを知らせる重要なサインです。
このエラーを解決するためのポイントをまとめると以下の通りです。
| チェック項目 | 確認内容 |
|---|---|
| 関数の戻り値型 | voidになっていないか。値を返す必要があるなら型を変更する。 |
| 代入操作 | 戻り値がない関数を、変数に代入(var = func())していないか。 |
| 条件式での使用 | if文やwhile文の条件としてvoid関数を使っていないか。 |
| プロトタイプ宣言 | 関数の宣言と定義で、戻り値の型が一致しているか。 |
まずはエラーが出た行を特定し、そこで呼び出されている関数の定義を一つずつ確認しましょう。
関数の役割が「値を返すこと」なのか「処理を行うこと」なのかを明確に区別することで、より堅牢で読みやすいコードを書くことができます。
型システムを正しく理解し、コンパイラからのメッセージを味方につけることが、C言語上達の近道です。
