プロが教える店舗&オフィスのセキュリティ対策術

#include <stdio.h>
#include <stdlib.h>

void *Run(){
printf("run¥n");


int main(){

(*Run)();
Run();

return 0;


実行結果
run
run

この場合、(*Run)()とRun()は何故同じ結果になるのでしょうか。

なお、このプログラムはWindowsで実行した場合、関数ポインタのところでno return statement in function returning non-voidという 警告(warning)が発生しましたが、Linuxで実行した時は何事もありませんでした。

質問者からの補足コメント

  • Linuxで実行した時は ×
    Linuxでコンパイルしたときは○

      補足日時:2017/08/19 22:29

A 回答 (2件)

関数名だけのときは、その関数へのポインタという扱いになる


つまり
Run == &Run
です。
(* Run )() → (* (& Run) )() → Run()
です。


なお、
void * Run ()
と定義したものは
「void * (void型へのポインタ)」を返す関数 Run
であって
「void 型関数へのポインタ」の変数Run
ではありません。

void * を返す、と宣言しているのに、実際にはreturn が無いので、その警告が出ています。
「voidでない(値を返す)関数なのに、(値を返すための)return文が無い」という意味です。

> Linuxで実行した時は何事もありませんでした

(実行ではなく、コンパイルですよね?)
単に、警告表示レベルが低く設定されていて、表示されなかっただけです。
-Wall 等で warning: control reaches end of non-void function [-Wreturn-type] が表示されます。
    • good
    • 0
この回答へのお礼

指摘のあった通り、実行ではなくコンパイルです。すいません。
ありがとうございます。

お礼日時:2017/08/19 22:26

C では, 関数呼び出し


F(...)
における F は「関数へのポインタ」である必要があります. また, 関数型の式 (関数指示子) は次の 2つの場合を除き関数へのポインタに変換されます:
・sizeof のオペランドの場合 (ただし関数型に対して sizeof を適用することはできないので, この場合は自動的にエラーになる)
・単項 & のオペランドの場合

従って, Run() という式は
1. Run は関数指示子である
2. これは sizeof のオペランドでも単項 & のオペランドでもないので, 関数 Run へのポインタに変換される
3. その「関数 Run へのポインタ」に対して関数呼び出し演算子 () を適用する
4. よって関数 Run を呼び出す
という意味になります.

一方 (*Run)() では (ちょっと途中を省略するけど)
1. Run は関数 Run へのポインタに変換される
2. *Run で「関数 Run を表す関数指示子」になる
3. 関数指示子 *Run は sizeof のオペランドでも単項 & のオペランドでもないので関数 Run へのポインタに変換される
4. 結局関数 Run を呼び出す
という処理です.

同じ理由で
(**********Run)()
でもやっぱり関数 Run を呼び出すことができます. たぶん誰もやらんけど.
    • good
    • 0
この回答へのお礼

ありがとうございます

お礼日時:2017/08/20 07:39

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!