4

重複の可能性:
異なるセマンティクスを持つ関数呼び出し

私はCの関数ポインタについて読んでいます。私はこのプログラムを試しました:

#include <stdio.h>

int foo(void)
{
    printf("At foo.");
    return 0;
}

int main (void)
{
    printf("%p\t%p\t%p\n", &foo, foo, *foo);
    return 0;
}

このプログラムの出力は次のとおりです。

0040138C    0040138C    0040138C

1次元配列<datatype> <identifier>[N]では、は同じ値identifier&identifier指しますが、値の性質は異なります。1つは型datatype*で、もう1つは1-D配列への型ポインターです。同様に、関数の場合、foo&fooは同じです。しかし、どうですか*foo、そしてその性質は&foo, foo, *foo何ですか?

4

2 に答える 2

4
于 2012-08-11T07:53:21.560 に答える
1

C/C++ では、関数は 2 つの方法でしか使用できません。そのアドレスを取得する方法と、それを呼び出す方法です。それ以外のことはできません。

つまり、foo関数そのものです。C++ には標準の変換があり4.3 Function-to-pointer conversionます。これは、fooが自動的に に変換されることを意味し&fooます。記法&&&&fooは構文エラーになります。

C++5.3.1.1 Unary operatorsには、関数ポインターを関数自体の結果で逆参照できるようにする表現があります。これは、複数*の 's が許可されないことを意味します。それでも、少なくとも MSVC と GCC では動作します。おそらくこれはFunction-to-pointer conversion、次の操作を処理する前に、コンパイラが逆参照の直後に適用されるためです。

*関数で複数のを許可し、複数の を許可しない正当な理由がわかりません&。何らかの理由で、*および&操作に対して異なるロジックが実装されています。

このポインタへのキャストと逆参照fooを試みることができます。char*マシンコードのバイトが含まれます。これらのバイトの長さは不明です。このアドレスの読み取り/書き込み保護も不明です。多くの CPU アーキテクチャでは、読み取りビットと書き込みビットを設定せずに実行ビットを設定できます。そのため、関数を呼び出すことはできますが、このアドレスを読み込もうとするとクラッシュする可能性があります。

于 2012-08-11T19:01:52.150 に答える