- 締切済み
関数の引数表記なしについて
はじめまして。C言語初心者です。 質問させてください。 関数を宣言して引数を表記しないで使用することは可能なのでしょうか? またどのような場合に使用するのでしょうか? 例として以下コードになります。 ----------------------- #include<stdio.h> int test1(int a); void test2(int b); void main(){ int i = 0; int j = 0; //この部分 i = test1; printf("%d\n", i); //この部分 j = test2; printf("%p\n", j); } int test1(int a){ return a + 1; } void test2(int b){ printf("test"); } --------------------------- 出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 詳しい方がいらしましたら教えてください。 宜しくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- ency
- ベストアンサー率39% (93/238)
youdoukouさん、ポインタは大丈夫なんですよね? int hoge; int *p_hoge; p_hoge = &hoge; とした場合、p_hoge は「int型 (の変数) を指すポインタ」で、p_hoge には「int型変数 hoge を指すポインタ値 &hoge」が設定されることになります。 また、同様に int piyo[10]; int *p_piyo; p_piyo = piyo; とした場合、p_piyo は「int型 (の変数) を指すポインタ」で、p_piyo には「int型配列 piyo の先頭要素を指すポインタ値 &piyo[0]」が設定されることになります。 考え方は、これと同じなんです。 ただ、変数が関数になっただけなんですね。。。 void func( int ); void (*p_func)( int ); p_func = func; とした場合、p_func は「int型の引数をとり戻り値のない関数を指すポインタ」で、p_func には「int型の引数を取り戻り値のない関数 func を指すポインタ値 func」が設定されることになります。 ちなみに、これは次のように書いても同じ意味です。 p_func = &func; また、p_func を使って関数コールをする場合には、次のようにします。 (*p_func)( 5 ); ただし、次のようにしても良いことになっています。 (p_func)( 5 ); p_func( 5 ); ということは、(*) は意味を成さないことになりますので、こんなのも文法上は問題ありません。 (**********p_func)( 5 ); # こんなふうに書く意味は、まったくありませんけどね。。。 ちなみに、ポインタの値を printf() で表示させる場合には、"%p" を使います。 ポインタの値を処理系にあった形で表示してくれます。 # たいていの処理系ではポインタはアドレスで実装しているので、アドレスが # 表示されることになると思います。
- matyrcry
- ベストアンサー率47% (101/213)
関数名はその関数を実行するためにジャンプ処理をするために利用 する関数の先頭アドレスになります。 有効にプロトタイプ宣言できなかったり複数の関数を状況に応じて 切り替えて実行したいときなどにたまに便利です。 関数の配列を作ったり、関数の引数として関数アドレスを渡してみ るとか。 int test1(int a) を int testSub( void *adr,int a ) { int b; int (*func)(int); func = (int(*)(int))(void*)adr; b = (*func)(a); return b; } を作れば j = testSub( (void*)test1,i ); という感じにコールできます。
- galluda
- ベストアンサー率35% (440/1242)
がると申します。 んっと…初心者さんであるのなら、取り合えず「関数は必ず引数を明示的に記述する」事を覚えておけばよいと思います。 youdoukouさんがなさったのは「関数ポインタ」と呼ばれるもの(とそれを扱うための記述)になりまして。 ある程度慣れてから使うと大変に便利ではあるのですが、いきなり使うとよくわからなくなってしまうので、後々、にしたほうが無難です(苦笑 それでも興味があったら、googleあたりで「関数ポインタ」について調べてみるとよいかと思います。
> 関数を宣言して引数を表記しないで使用することは可能なのでしょうか? 「引数を表記しない」とは「引数に何も与えない」の意味と取って回答します。 C では何も引数を与えない場合でも、関数の呼び出しに括弧は必須です。よって、例のコードでは i = test1(); や j = test2(); とする必要があります。 しかし、多分このように記述された場合、コンパイラーによっては Warning か Error が出ると思います。しかし、(詳しくは述べませんが)この記述でも形式的には正しい(辻褄のあった)バイナリコードに落とす事もできるため、Warning しかでない場合や、何も出なかった場合、一応実行可能なファイルが生成できると思います。 ですが、実行した結果はおそらく予期しない結果になると思います(例のコードの場合、test1 の a や、test2 の b が与えられなかった場合、その正しい結果も予期できない(何が正しいのか判らない))。 ですから、 > またどのような場合に使用するのでしょうか? そのような場合は存在しないと思います。 == しかし、C++ の場合は、予め引数のデフォルト値を定義しておく事が出来ます。例えば、 int test1(int a=0); のような形です。 この場合、 i = test1(); は、i = test1(0); と等価で、意味はあります。 主に、「殆どの場合、与えられる引数は固定であるが、極々稀に違う引数を与える事がある」ような場合に、この引数のデフォルト値を使います。
- TT414
- ベストアンサー率18% (72/384)
>出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 i=test1; は関数のアドレスをiに代入します。 ただしiはint型、test1は(void (*)(int a))型なのでウォーニングが表示されます。 正式には以下のようにしてください。 int test1(int a); void test2(int b); void (*i)(int a) =NULL; int (*j)(int a) =NULL; i = test1; printf("%p\n", i); j = test2; printf("%p\n", j); 上記の場合 i(1); を実行すると test1(1); と同様に動きます。