C言語のコンパイラ エラー C2070の原因と対策について解説
この記事では、C言語で発生するコンパイラ エラー C2070について説明します。
sizeof演算子は式または型名を対象にする必要があり、関数名など不適切な引数を渡すとエラーが発生します。
具体例を通して、エラーの原因と正しい使い方を解説しています。
エラー C2070の原因と背景
このセクションでは、コンパイラエラー C2070 の原因となる sizeof
演算子の仕様と、その利用時に起こる誤りについて説明します。
sizeof演算子の仕様
sizeof
演算子は、引数に式または型名を取る演算子です。
どちらの場合も、対象のメモリ上のサイズ(バイト数)を返すのですが、使い方には以下のような違いがあります。
式と型名の区別
sizeof
の引数として式を渡す場合は、変数や計算式などが対象になります。
たとえば、変数 a
に対して
sizeof(a)
と書くと、変数 a
の型によって適切なバイト数が返されます。
一方で、型名を渡す場合は、
sizeof(int)
のように記述し、括弧に型名を入れる必要があります。
この区別は、型情報を正しく取得するために必須です。
許容されないオペランドについて
sizeof
演算子は、使用する対象に制限があります。
特に、関数やラベルといった一部のオペランドは対象外です。
関数名そのものを sizeof
演算子に渡すことは、言語仕様上許容されておらず、C2070 エラーが発生します。
そのため、関数を対象とする場合は、関数ポインタに変換した上でサイズを調べるなど、別の方法を用いる必要があります。
関数名とsizeofの関係
関数名の扱いは、他の型や変数とは大きく異なります。
関数を直接 sizeof
で扱うことはできませんが、関数のアドレス(関数ポインタ)として扱う場合は、別の考え方が必要となります。
関数とそのアドレスの違い
C言語では、関数名は関数の先頭アドレスを示すため、実態としてはアドレスとみなされることがあります。
しかし、関数そのものに対してメモリ上の大きさという概念は存在しません。
そのため、
sizeof(func)
のように関数名を直接 sizeof
演算子に渡すとエラーになります。
関数のアドレスを扱いたい場合は、関数ポインタに明示的にキャストするか、関数ポインタ変数を経由してサイズを確認する方法が考えられます。
誤った使用例の分析
よく見られる誤りは、以下のように関数名を直接 sizeof
演算子に与えてしまうケースです。
#include <stdio.h>
// サンプル関数
void func() {
// サンプル処理
}
int main(void) {
int size;
// 関数名を直接渡しているためエラーが発生する
size = sizeof(func);
printf("Size: %d\n", size);
return 0;
}
上記のコードでは、関数 func
を直接 sizeof
の引数として渡しているため、コンパイラエラー C2070 が発生します。
関数名に対しては、明示的なキャストや適切な代替手段を用いる必要がある理由がここにあります。
コード例によるエラー検証
このセクションでは、実際にサンプルコードを用いてエラー C2070 の原因となる誤った使用例と、その修正例を示します。
エラー発生例の紹介
誤ったコード例の構造
以下のサンプルコードは、関数名 func
を直接 sizeof
演算子に渡した場合の例です。
#include <stdio.h>
// 関数の宣言
void func(void) {
// サンプル関数の処理
}
int main(void) {
int size;
// 間違った sizeof の使用例:関数名を直接引数にしているためエラーが発生する
size = sizeof(func);
printf("Size: %d\n", size);
return 0;
}
このコードをコンパイルすると、エラーメッセージが表示され、sizeof
に対して不正なオペランドが渡されている旨が伝えられます。
エラー箇所の特定方法
コンパイラが出力するエラーメッセージには、
「type: sizeof オペランドが正しくありません」
という形式で表示されるため、このメッセージを手がかりにエラー箇所を特定できます。
上記のコード例では、関数名 func
に対して sizeof
を使用している行がエラーの原因となっていることが明確です。
修正コード例の提示
正しいsizeofの利用方法
正しい方法としては、例えば変数に対して sizeof
を使用するか、関数ポインタとして扱う方法があります。
関数ポインタに対してサイズを調べる場合は、明示的に変数に代入してから使用する方法が一般的です。
以下に、正しい使用例を示します。
#include <stdio.h>
// 関数の宣言
void func(void) {
// サンプル関数の処理
}
int main(void) {
int sizeVar;
// まず変数 a に対して sizeof を利用(正しい使用例)
sizeVar = sizeof(int);
printf("Size of int: %d\n", sizeVar);
// 関数ポインタとして func のアドレスを取得し、そのサイズを調べる方法
void (*funcPtr)(void) = func;
int sizeFuncPtr = sizeof(funcPtr);
printf("Size of function pointer: %d\n", sizeFuncPtr);
return 0;
}
Size of int: 4
Size of function pointer: 8
このサンプルコードでは、変数と関数ポインタの両方で正しい sizeof
の使い方を示しています。
修正前後の比較
以下に、修正前と修正後のコードの違いをリストにまとめます。
- 修正前
sizeof(func)
と直接関数名を指定している- コンパイラエラー C2070 が発生する
- 修正後
- 変数や関数ポインタを対象に
sizeof
を正しく利用している - エラーなくコンパイルが可能
- 変数や関数ポインタを対象に
コンパイラエラーメッセージの詳細解析
このセクションでは、エラー C2070 が発生した場合のコンパイラエラーメッセージの内容と、その発生プロセスについて詳しく解説します。
C2070エラーメッセージの内容
メッセージ構造の確認
C2070 エラーは、コンパイラが受け取った sizeof
のオペランドが正しくない場合に発生します。
エラーメッセージは、以下のような形式で出力されることが一般的です。
- 「type: sizeof オペランドが正しくありません」
- 「関数名を直接対象とすることはできません」などの補足説明が含まれる
これにより、どの行でどのような誤りがあったのかが明確になります。
エラー発生のプロセス解析
コンパイル時、コンパイラはまず sizeof
演算子に渡された対象を解析します。
対象が式の場合はその型が評価され、型名の場合は括弧内の型情報が確認されます。
しかし、関数名の場合はそのメモリレイアウトやサイズ情報が定義されていないため、
解析時にエラーが発生し、C2070 エラーとなる仕組みです。
対策と改善方法
このセクションでは、エラー発生時のコード修正手順や、開発環境での検証方法について説明します。
コード修正の手順
修正のポイント説明
エラー C2070 を解消するには、対象となるオペランドが正しいかどうかを確認する必要があります。
以下の手順に沿って修正することをおすすめします。
- 間違った
sizeof
の使用例(例:関数名を直接渡す)を特定する - 関数名を使用する場合は、関数ポインタにキャストまたは変数に代入してから使用する
- 本来意図している対象(例:変数や型)に対して
sizeof
を適用する
開発環境での検証方法
修正後は、以下の方法で検証が可能です。
- ソースコードを保存した上でコンパイルする
- コンパイラの出力メッセージを確認し、エラーが解消されているか確認する
- サンプルコードで
printf
により出力結果を確認し、意図した動作をしているかをチェックする
注意すべきポイント
同種エラーの事例比較
コンパイル時に表示されるエラーメッセージは似た内容のものが複数存在する場合があります。
たとえば、sizeof
以外にも使用できないオペランドに対して同様のエラーが表示されることがあります。
そのため、エラーメッセージ中の「sizeof オペランドが正しくありません」という文言に着目し、
どこに問題があるかを慎重に確認することが重要です。
関数使用時の確認方法
関数を対象とする場合、直接 sizeof
を使用するのではなく、必ず関数ポインタとして扱う方法を検討してください。
関数ポインタの場合、サイズは通常、ポインタ型のサイズとなりますので、
正しく動作することが確認できます。
また、意図しない型変換や、キャストの漏れに注意する必要があります。
まとめ
この記事では、sizeof演算子の正しい使い方と、エラー C2070 の原因を解説しています。
式と型名の違い、関数名と関数ポインタの取り扱いの注意点を明確にし、誤った使用例と修正例を通してエラーの発生理由と対策を説明しました。
また、コンパイラエラーメッセージの解析と実際の開発環境での検証方法も紹介し、適切なコード修正のポイントについてまとめています。