関数へのポインタの質問です。
下のように、関数へのポインタを使ったプログラムを書きました。
(関数へのポインタを理解するためのものなので、実用的な意味はありません。(*^_^*)
また、このプログラムはコンパイルもリンクも実行も問題なく出来ます。)
#include <stdio.h>
int add_func(int,int);
(*func_p0) (int,int);
int main(void)
{
int (*func_p1) (int,int);
int (*func_p2) ( );
int hoge0,hoge1,hoge2;
func_p0=add_func;
hoge0=func_p0(3,5);
printf("0 : 3+5は%d\n",hoge0);
func_p1=add_func;
hoge1=func_p1(3,5);
printf("1 : 3+5は%d\n",hoge1);
func_p2=add_func;
hoge2=func_p2(3,5);
printf("2 : 3+5は%d\n",hoge2);
return(0);
}
int add_func(int x, int y)
{
return(x+y);
}
func_p0のように戻り値の型を書かない場合と、func_p1やfunc_p2のように戻り値の型を書くのとでは何が違うのでしょうか。
func_p0は外部変数ですが、自動変数にする(main関数の中で同様に宣言。)とコンパイルエラーになります。
それはなぜですか。
func_p1のように引数の型が書いてあるのと、func_p2のように引数の型が書いていないのでは何が違うのでしょうか。
int (*func_p2) ( );というのは、int (*func_p2) (void);とは違うんですよね?
A 回答 (1件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
> func_p0のように戻り値の型を書かない場合と、func_p1やfunc_p2のように戻り値の型を書くのとでは何が違うのでしょうか。
見た目が違います(いや、冗談ではなく)。
Cの場合、関数の宣言で、戻り値を省略した場合には int を返す関数だと解釈する、と
規格で決められています。
また、外部変数の場合には、型を省略すると int である、と解釈します(古いスタイル
なので、警告が出るはず)。
あと、次の質問にあるように、記述できる場所が変わってきたりする、という副作用が
あるようですね。
> func_p0は外部変数ですが、自動変数にする(main関数の中で同様に宣言。)とコンパイルエラーになります。
> それはなぜですか。
それは、コンパイラによって挙動(エラーにするかどうか)が変わってくるかもしれません。
コンパイラは、関数の中に入ると、変数の宣言か実行文の記述があると解釈してゆくのですが、
変数の宣言は「型」として有効なシンボルであること、実行文は「予め宣言されたシンボル」
であることが、求められます。
> func_p1のように引数の型が書いてあるのと、func_p2のように引数の型が書いていないのでは何が違うのでしょうか。
関数の宣言で引数が省略された場合には、可変個の引数である、と解釈されます(これも
規格で定められています)。「可変個の引数」というのは、例えば、printf() の二番目などです。
int (*func_p2)(); は、 int (*func_p2)(...); と等価です。質問に書かれている
通り、int (*func_p2)(void); とは別ものです。
因みに、c++ の場合には、引数を省略した場合には、void と解釈されます。
この回答への補足
>Cの場合、関数の宣言で、戻り値を省略した場合には int を返す関数だと解釈する、と規格で決められています。
手元にある「新ANSI C言語辞典」という本によると、
関数宣言には、関数原型を宣言する場合と、関数へのポインタを定義する場合があるそうですね。
今、質問しているのは、関数へのポインタの件なので、
質問で挙げた例で言うと
(*func_p0) (int,int);
というのは、
int (*func_p0) (int,int);
と同じなのだ、
ということがおっしゃりたいのですね。
>また、外部変数の場合には、型を省略すると int である、と解釈します(古いスタイルなので、警告が出るはず)。
すみません。こっちは上とどう違うのかよくわかりません。例を挙げてください。
変数宣言なしに変数を使うと、それをint型の変数とみなす、という意味ですか?
(ちなみに質問で挙げたプログラムは、1つの警告も出ません。)
#そういうことではないのかな。あまり深い意味はないのでしょうか。
残念ながら、func_p0をmain関数の中で宣言するとエラーになる理由はわかりませんでした。
もっとも、
intを返す関数へのポインタを定義するときは、必ずintを書いておけば問題ないわけですね。
>int (*func_p2)(); は、 int (*func_p2)(...); と等価です。質問に書かれている通り、int (*func_p2)(void); とは別ものです。
int (*func_p2) ( );のように引数の型を書かないときは、引数の型がどのような関数でも指すことが出来る。
だから、int add_func(int,int); というのも指すことができる。(←これは質問のプログラム中に既出)
いうまでもなく、下のプログラムのように、int ret9_func(void); も指せる。
また、標準関数のprintfは int printf( const char * , ... ); です。そういう関数を指すこともできる。
ですから、下のように、func_p2=printf; という代入も全く問題ないわけですね。(実際、問題なく動作した。)
#include <stdio.h>
int ret9_func(void);
int main(void)
{
int (*func_p2) ( );
func_p2=ret9_func; /* 引数がvoidの関数を代入 */
printf( "関数func_p2の戻り値は%dです。ret9_funcのことですね。\n\n", func_p2() );
func_p2=printf; /* 引数が可変個の関数printfを代入 */
func_p2("func_p2=printf;をやりました。func_p2はprintfと同じですよね。\n");
return(0);
}
int ret9_func(void)
{
return(9);
}
#実用的な意味にとぼしいですが。;^_^A
以上のことから考えるに、 int (*func_p2) ( ); と定義すれば、どんな「引数」の関数でも指すことができるわけですけど、
「戻り値」の型がどのような関数でも指すことができる、なんてのはできないんですね?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
visualstudio C# テキストボッ...
-
typedef enumの使い方を教えて...
-
0除算を判定したい
-
DLLでLIBファイルが作成されない
-
コンストラクタについて
-
C++のfor文について
-
DWORDの実際の型は何でしょうか
-
C++でboolにintの値を代入する...
-
vector<int> に Serialize を使...
-
仮想基底クラスをもつクラスの...
-
main.c:7:43: warning: implici...
-
二つ以上の値を返す関数
-
引数の受け渡し
-
C#について
-
相互参照するクラス、俺こんな...
-
コンパイルすると error C1083 ...
-
C言語での方向キー入力判定
-
エラー「invalid conversion fr...
-
2重定義って??
-
2÷3などの余りについて
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
visualstudio C# テキストボッ...
-
C++のfor文について
-
2重定義って??
-
long型の定数の末尾にLを付ける...
-
typedef enumの使い方を教えて...
-
main.c:7:43: warning: implici...
-
C++でboolにintの値を代入する...
-
構造体の要素すべてに対する四...
-
intとINTの違いは?
-
ハンドルされていない例外が発...
-
DDVによるメッセージの変更
-
変数の型を定義しなかった場合...
-
【#define】 defineで定義した...
-
C++ クラスをメンバにもつクラ...
-
構造体の宣言でエラーが出ます。
-
プログラムの中で別のmainを呼...
-
void func( void )について
-
エラー「invalid conversion fr...
-
関数の実体定義にヘッダファイ...
おすすめ情報