2017-12-07 11 views
0

せずに関数ポインタを初期化私は関数ポインタで遊んで、かつ直感的に以下のコードを見てみましょうC.「&」演算子

内のポインタの私の理解に合わないものに走りました。 :私はCの他のポインタのような関数ポインタを扱う場合

include <stdio.h> 

void fun(int a) { 
    printf("fun, %d!\n", a); 

} 

void bun(int b) { 
    printf("bun, %d!\n", b); 
} 


int main(){ 

    void (*fooptr)(int) = &bun; 
    void (*blooptr) (int) = fun; 

    fooptr(200); 
    blooptr(100); 

    return 0; 
} 

、私は互換性のない型に対してコンパイラの警告をトリガするvoid (*blooptr) (int) = fun;を期待するべきです。私のコードは(サイレントに)コンパイルされ、期待どおりに動作します。

Cは、コンパイラの警告さえなくても、普通のポインタを実行するのと同じように、&演算子を使用せずに関数ポインタを初期化できますか?これは私が間違って適切な振る舞いをしているケースの1つですが、私は技術的にはの未定義の動作です領土ですか?もしも誰かがを説明できるのであれば、これはうまくいくでしょう。なぜなら、関数ポインタの本質にいくつかの洞察力(文献への言及もあります)があるからです。

この特定の質問を探してみましたが、関連するものは見つかりませんでした。ちょっと基本的なようだから、それがダブだと謝ります。

+0

これは、配列を渡すようなものです - Cは、矛盾した、混乱しているアドレスを保持するだけで、時にはアドレス演算子を必要とします:( –

答えて

0

Cの関数型は、関数ポインタ型に自動的かつ暗黙的に崩壊します(unary &演算子がquietyを適用した場合のように)。この減衰は、単体の&演算子とsizeof演算子を除き、すべてのコンテキストで発生します。このため

void (*fooptr)(int) = &bun; 

void (*fooptr)(int) = bun; 

は同じことを言うには、2つの代替的な方法です。

+0

この部分は展開できますか? "この崩壊は単項演算子とsizeof以外のすべてのコンテキストで行われます演算子 " – aspen100

+0

@ aspen100:'&bun'を実行したときを除いて、式 'bun'は静かに'(void(*)(int))bun'と解釈されることを意味します( '&(void(* )(int())bun')と 'sizeof bun'(これは' sizeof(void(*)(int)bun'と解釈されません)を除いて、 'sizeof'の無効なアプリケーションとして解釈されます)。それ以外の文脈では、 'bun'は'(bun(*)(int))bun'と同じです。これは '&bun'と同じです。 – AnT