3

関数へのポインタで何かをしたとき、私は何かに気づき、理解できませんでした

これは私がしました:

#include <stdio.h>

int callback(void)
{
   return 5;
}

void call(int (*cpmpare)(void))
{
    int x;
    x = cpmpare();
    printf("%d", x);
}

void main()
{
    int (*compare)(void);
    int *a, b;
    b = 5;
    a = &b;
    compare = callback;
    printf("%p\n", &callback);
    printf("%p\n", compare);
    call(&callback);
}

そして、私はcompare = &callback代わりcompare = callbackにそれを行い、同じことを行いました。比較は、コールバックと同じアドレスを取得しました。

なぜ両方の方法で機能したのですか?

私が知っていることから、ポインターと通常の変数を比較するのは間違っているでしょう。

4

2 に答える 2

6

配列のような関数は、一部のコンテキストではポインターに分解されます。&functionorを使用するのはほとんどの場合同じfunctionです。あなたの例では、間違いなくそうです。これら 2 つのステートメントは意味的に同じです。

compare = callback;
compare = &callback;

これらの2つは次のとおりです。

call(&callback);
call(callback);

同様に、関数ポインタを使用*する場合、これもオプションです。

x = cpmpare();
x = (*cpmpare)();
于 2013-05-27T16:28:27.833 に答える
4

C 委員会は、(意味が明確だったので) 関数の名前 (関数を呼び出すための括弧が後に続かない) が関数のアドレスに評価されることを決定しました (配列の名前が評価されるのとほぼ同じ方法で)。配列の先頭のアドレス)。

公式の文言は次のとおりです (§C99、6.3.2.1/4):

関数指定子は、関数型を持つ式です。sizeof 演算子または単項 & 演算子のオペランドである場合を除き、型「関数を返す型」を持つ関数指定子は、型「関数を返す型へのポインタ」を持つ式に変換されます。

Bjarne や C++ 委員会がこのアイデアにそれほど興奮していたかどうかはわかりませんが、彼らはこれに賛成することに決めたようで、C++ でも同じことが言えます。彼らがこれについて熱心ではなかったと私が思う(主な)理由は、メンバー関数を呼び出すために括弧が続かないメンバー関数の名前で同じことを行うことができたにもかかわらず、そうしないことを選択したためです-メンバー関数へのポインターには、アドレス演算子 ( ) を使用する必要&があります。

于 2013-05-27T16:30:08.773 に答える