1

古いバージョンのDiabCコンパイラを使用しています。

私のコードでは、関数名を取得し、同じシグネチャを持つ関数ポインタとして再定義しました。この変更を行う前に、コードは機能していました。変更後、組み込みシステムがロックされました。

関数ポインタは、ヘッダーでexternとして宣言され、1つの.cファイルで定義され、別の.cファイルで使用されました。2番目の.cファイルから呼び出されると、システムがロックアップします。sprintfを使用してデバッグ情報を追加しようとすると、最終的にそれが未定義のシンボルであることがわかりました。ヘッダーファイルが2番目の.cファイルに含まれていないことに気付きました。#includeすると、すべてがコンパイルされ、正しく機能しました。

私の質問は、シンボルが呼び出し場所で定義されていなくても、コンパイラが関数シグネチャを推測できるようにするCルールはありますか?私の理解では、変更を加えるずっと前にエラーがあったはずです。

4

2 に答える 2

1

ほとんどの場合、コードは C89 または同様のモードでコンパイルされているため、最初は機能していました。1989 年の C 標準では、最初に関数を宣言せずに関数を呼び出すことができます。

ポインターを使用するようにコードを変更したが、ポインターの宣言を含めなかった場合、コンパイラーは、ポインターが実際には関数であると想定し、ポインターが内部に実行可能コードを持っているかのように、ポインターを呼び出すコードを生成しました。その結果、当然のことながら、プログラムは機能しなくなりました。

あなたがすべきことは、特にプロトタイプなしで関数を呼び出す場合に、すべての可能な警告を有効にすることです( gcc:-Wallの場合、-Wextra最適化が有効になっていることを確認してください(-O2コード分析が有効になるため))。より良い方法は、コンパイラを C99 モード ( -std=c99gcc で) に切り替えるか、C99 コンパイラに切り替えることです。1999 年の C 標準では、プロトタイプなしで関数を呼び出すことは禁止されており、C89 にはないいくつかの便利な機能が付属しています。

于 2013-02-22T00:33:05.663 に答える
1

宣言が使用できない場合、コンパイラは、不明な数の引数を取り、int を返す関数の既定の宣言を使用します。コンパイラの警告を表示する場合 (たとえば-Wall -Wextra -Werror、gcc を使用している場合は、コンパイラのドキュメントを確認してください)、コンパイル時に警告が表示されるはずです。

于 2013-02-22T00:18:39.520 に答える