簡単な質問:
strlen[char*]
#include <string.h>
私かどうかに関係なく完璧に動作します
コンパイラから取得するのは暗黙の宣言に関する警告だけですが、機能的には意図したとおりに機能します。
何故ですか?
未定義の動作を呼び出す場合、考えられる動作の1つは、プログラムが期待どおりに動作し、システムが1つ、インストールしたライブラリとシステムソフトウェアの現在のバージョンで動作することです。これは、これを実行しても問題がないという意味ではありません。実際、正しいC99コンパイラは、暗黙的な関数宣言を許可するべきではありません。エラーが発生するはずです。
Cの関数プロトタイプは必須ではありません。これらは、渡された型の型チェックを実行できるように、コンパイラーにとって有用な指標です。を含めない場合string.h
、関数にはデフォルトの署名が想定されるため、警告が表示されます。
スコープ内にプロトタイプなしで関数が呼び出された場合、コンパイラーは、渡されたパラメーターのタイプを受け入れ、整数の結果を受け入れる関数を呼び出すコードを生成します。パラメータが関数が期待するものと一致し、関数が呼び出し元のコードが処理できる方法で結果を返す場合(*)、すべてがうまくいきます。プロトタイピングの目的は、可能であれば引数が期待される型に変換され、変換できない場合はコンパイルが失敗するようにすることです。たとえば、プロトタイプ化されていない関数が「long」型の引数を予期し、「int」を渡そうとすると、次のいずれかが発生する可能性があります。
対照的に、関数のプロトタイプが作成された場合、コンパイラは、関数を呼び出す前に「int」を「long」に変換するために必要なことをすべて実行することが保証されます。
Cが最初に考案されたとき、プロトタイプは存在しませんでした。プログラマーは、すべての引数が期待される正確な型で渡されるようにする責任がありました。実際には、すべての関数の引数が常に正確に適切な型であることを確認するのは非常に困難です(たとえば、長い値を期待する関数に値5を渡す場合は、「5L」または「(long)5」のいずれかとして記述する必要があります。 )。現実的に言えば、可変個引数関数を除いて、暗黙の引数型に依存する理由はありません(**)。
(*)関数が「int」を返すことが期待され、関数の実際の戻り値が「int」に収まる場合を除いて、誤ったパラメーター型で発生する可能性のあることはすべて、誤った戻り型で発生する可能性があります。誤ったパラメータタイプが使用されている場合よりも正しい可能性が高くなります。
(**)私が考えることができる唯一の例外は、プロトタイプ対応コンパイラが利用できない非常に古いハードウェアをプログラミングしていた場合、またはコードゴルフまたは同様の競争のためにプログラミングしていた場合です。後者はプログラミングではなくパズルを解くことを考えており、前者の条件が当てはまるハードウェアを人々が使用することに興味があるかどうかはわかりません。
それは宣言であるため、つまりいわゆる「デフォルト宣言」に等しいからです。コンパイラは、未知の関数がintを返し、コードで関数を初めて使用するときに渡されるパラメータを期待します。
通常、これは、インクルードした別のヘッダーファイルにもstring.hが含まれているためです。明らかに、他の何かが含まれているという理由だけで何かを含める必要がないと想定することは悪い習慣ですが、この影響の原因である可能性が最も高いです。
これは、Cではintが関数から返されるデフォルトのデータ型であるためだと思います。より完全なコード例を教えてください。
関数プロトタイプはインクルードファイルにあります。したがって、これらのファイルを含めなくても、固定のプロトタイプint function_name();
が作成されます。これで、のコードがstrlen()
実行時にリンクされるライブラリファイルにあるため、関数は正しい出力を提供します(プロトタイプが固定されている唯一の関数である場合のみint function_name();
)。