5

これが事です、私はいくつかの機能を持っています、

void foo() {}
void bar() {}

そして、これらの関数を通常のオブジェクトのポインターと同じように渡したいのですが、

int main()
{
    void (*fptr1)() = foo;
    void (*fptr2)() = fptr1;
    void (*fptr3)() = bar;

    if (fptr1 == foo)
        printf("foo function\n");
    if (fptr2 == foo)
        printf("foo function\n");
    if (fptr3 == foo)
        printf("foo function\n")
}

これらの関数ポインタをこのように使用できますか? そして、それをテストするプログラムを書きましたが、大丈夫のようです。stackさらに、やに存在する可能性のある通常のオブジェクトとは異なりheap、関数は に存在すると思いますtext segment(そうですか?) ので、 を参照すると、テキスト セグメント内のfoo関数が存在する物理アドレスがわかりますか?foo

ファローアップ

実際に DLL を使用している場合は、これを考慮してください。まず、関数 ptr に関数fptrが割り当てられます。

ReturnType (*fptr)(ArgType) = beautiful_func;

ここで 2 つのシナリオ、

1) beautiful_func が DLL に含まれていない場合は、これを使用しても安全fptrです。

2)それがDLLにある場合、後で、使用するのは安全ではないと思います。なぜなら、今では生まれてfptrいないまったく別の関数を参照している可能性があるからですよね?fptr

4

5 に答える 5

2

はい、C 標準では、関数ポインターを演算子 == および != と比較できます。たとえば、C11 6.5.9 から:

2 つのポインターが等しく比較されるのは、両方が null ポインターであり、両方が同じオブジェクト (オブジェクトへのポインターとその先頭のサブオブジェクトを含む) または関数へのポインターである場合のみです。

関数が存在する正確な場所は、プラットフォームによって異なります。テキスト セグメントにある場合もあれば、別の場所にある場合もあります。仮想メモリを備えたオペレーティング システムで実行している場合、アドレスは通常、物理メモリ アドレスではなく仮想アドレスです。

于 2012-11-28T08:14:16.287 に答える
2

関数 foo がテキストセグメントにある物理アドレスを教えてくれますか?

プリミティブまたはその他の特別な OS で作業している場合を除き、いいえ!

アドレスは物理アドレスではなく、仮想アドレスです。

基本的に、物理メモリよりもさらに大きなプログラムを許可するオペレーティング システムで採用されているメカニズムがあります。したがって、OS は舞台裏でマッピングを処理する仕事をします。

混乱させてすみません。あなたの理解は正しいです(関数ポインターを使用している方法で使用してもまったく問題ありません)が、アドレスは物理アドレスではありません(これは、メインメモリが実際にアドレス指定される数値を指します)。

于 2012-11-28T07:51:42.993 に答える
1

ポインターがメモリアドレスよりも格納されるという事実を考慮すると、これは数値になります。はい、そのように比較できます。hereから取得した他の質問については、テキストセグメントは「実行可能な命令を含む、オブジェクトファイルまたはメモリ内のプログラムのセクションの1つ」として定義されます。つまり、そのポインターには、テキストセグメント。

于 2012-11-28T07:49:06.123 に答える
0

はい、そのように使用できます。そして、あなたの理解は正しいです。

于 2012-11-28T07:44:28.537 に答える