関数を作成するときに、
int compar(const void *, const void *)
その名前をqsort
andのパラメーターの 1 つに渡すだけでbsearch
、これらの関数はどのようにして上記の本質的にランダムな単語を認識し (関数ポインターであると明示的に述べたことはなく、実際の関数であるため)、それをパラメーターとして使用するのでしょうか? qsort
andbsearch
または何かの関数宣言に明示的なキャストはありますか?
関数を作成するときに、
int compar(const void *, const void *)
その名前をqsort
andのパラメーターの 1 つに渡すだけでbsearch
、これらの関数はどのようにして上記の本質的にランダムな単語を認識し (関数ポインターであると明示的に述べたことはなく、実際の関数であるため)、それをパラメーターとして使用するのでしょうか? qsort
andbsearch
または何かの関数宣言に明示的なキャストはありますか?
qsort
これはおよび関数自体とは関係ありませんbsearch
。むしろ、関数名はコンパイラによって標準に従って関数ポインタに暗黙的に変換されますC11 6.3.2.1 Language / Conversions / Other operands / Lvalues, arrays, and function designators
。
関数指定子は、関数型を持つ式です。sizeof 演算子、_Alignof 演算子、または単項 & 演算子のオペランドである場合を除き、"型を返す関数" 型の関数指定子は、"型を返す関数へのポインター" 型を持つ式に変換されます。
つまり、(たとえば)に渡すcompar
と、渡されるのは関数への実際のポインターであり、「本質的にランダムな単語」ではありません。qsort()
関数識別子をそのアドレスとして暗黙のうちに扱う理由はずっと昔にありましたが (そして、このセクション全体は、私が知的な推論と考えたいことに基づいた私の推測ですが、決して決定的なものではありません)関数の値が意味をなさないためです。identifierint i = 5;
を使用すると、値 (5) があり、 を使用&i
してそのアドレスを取得することもできます。
ただし、関数の場合、実際にはそのような値はありません。それらを呼び出して値を生成xyzzy()
し、それらのアドレス を取得して、&xyzzy
後で関数ポインターを介して呼び出すことができます。
しかし、整数のようにアドレスとは別の本当の本質的な値i
はありません。そのため、初期のコンパイラ (ANSI より前) では、単純に省略形xyzzy
が&xyzzy
. もちろん、ANSI の本来の使命は、新しい言語を作成するのではなく、既存の慣行を成文化することであったため、ANSI はこの動作を維持しました。
K&R が別の方向に進んでxyzzy
、 と同じようにパラメーターを渡さない関数を呼び出す必要があると判断したxyzzy()
場合、世界は別の場所になるでしょう :-)