• 締切済み

関数の引数表記なしについて

はじめまして。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"); } --------------------------- 出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 詳しい方がいらしましたら教えてください。 宜しくお願いいたします。

みんなの回答

  • ency
  • ベストアンサー率39% (93/238)
回答No.5

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)
回答No.4

関数名はその関数を実行するためにジャンプ処理をするために利用 する関数の先頭アドレスになります。 有効にプロトタイプ宣言できなかったり複数の関数を状況に応じて 切り替えて実行したいときなどにたまに便利です。 関数の配列を作ったり、関数の引数として関数アドレスを渡してみ るとか。 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)
回答No.3

がると申します。 んっと…初心者さんであるのなら、取り合えず「関数は必ず引数を明示的に記述する」事を覚えておけばよいと思います。 youdoukouさんがなさったのは「関数ポインタ」と呼ばれるもの(とそれを扱うための記述)になりまして。 ある程度慣れてから使うと大変に便利ではあるのですが、いきなり使うとよくわからなくなってしまうので、後々、にしたほうが無難です(苦笑 それでも興味があったら、googleあたりで「関数ポインタ」について調べてみるとよいかと思います。

noname#168973
noname#168973
回答No.2

> 関数を宣言して引数を表記しないで使用することは可能なのでしょうか? 「引数を表記しない」とは「引数に何も与えない」の意味と取って回答します。 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)
回答No.1

>出力結果を見ると関数のアドレスが帰ってくるように思われますが、詳細が分かりません。 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); と同様に動きます。

関連するQ&A

  • 2次元配列を引数とする関数について

    2次元配列を引数とする関数について 私は今、2次元配列を引数とする関数の表を作るという課題に取り組んでいます。 条件として、int a[数字][数字]={{1,2,3...}}という配列の宣言と同時の初期化は使わず、 関数内で表の値を代入し、値を表示する関数を作り、事実上二つの関数を作るというものです。 私は以下のようなプログラムを作り、動かしましたが、[数字][数字]=********のような本来 あるべき実行結果とは異なる数字の羅列が出てきてしまいました。 ↓ #include <stdio.h> void func(int a[][6]); void fund(int b[4][6]); void main(void) { int a[4][6]; fund(a); func(a); } void func(int a[][6]) { int i,j,b[4][6]; fund(b); for(i=0;i<4;i++)        { for(j=0;j<6;j++) { printf("a[%d][%d]=%d\n",i,j,a[i][j]); printf("\n"); } } } void fund(int b[4][6]) { int i,j; for(i=0;i<4;i++) { for(j=0;j<6;j++)          { scanf("b[%d]*[%d]=%d\n",&i,j,b[i][j]); } } } 本来の実行結果 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 紙にも書いて何回も見直しましたが、どこがおかしいのかわかりませんでした。 どうすれば良いのでしょうか? 何か良いアドバイスをよろしくお願いします。

  • C言語のreturnの使い方

    return a, b; のように2つの引数で値を返せることを最近になり 知りました。ところで以下のような使い方は可能でしょうか? test( , )という2つの引数が必要な関数にnum()で return 1,2としてひとつの関数呼び出しで引数2個分に すると言うようなことです。 #include <stdio.h> int test( int i, int j){   printf("%d %d",i,j); } int num(void){   return 1,2; } int main(void){   test( num() ); }

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.

  • プログラミング(配列と関数の引数)

    a : ABCDE a : ABCDEFGH Len : 8 a : FGHIJ a : FGH a : FGH, c : FGH 上記のように表示されるプログラムを作りたいのですが、なかなかできません。下記のようなプログラムを作ったのですがどこが間違っているのかよくわかりません。分かる方、指摘をお願いします。 #include <stdio.h> void my_strcpy(char s[], char t[]); int my_strlen(char s[]); void my_strcat(char s[], char t[]); int main(){ char a[10]; char b[10] = "ABCDE"; char c[] = "FGH"; int len; my_strcpy(a, b); printf("a : %s\n", a); my_strcat(a, c); printf("a : %s\n", a); len = my_strlen(a); printf("Len : %d\n", len); my_strcpy(a, "FGHIJ"); printf("a : %s\n", a); a[3] = '\0'; printf("a : %s\n", a); if(strcmp(a, c) == 0){ printf("a : %s, c : %s\n", a, c); } int i, s, t; my_strcpy(a, b + 2); printf("a : %s\n", a); void my_strcpy(char s[], char t[]){ for (i = 0; t[i] != '\0'; i++){ s[i] = t[i]; } s[i] = '\0'; } int my_strlen(char s[]){ int i; for (i = 0; s[i] != '\0'; i++); return i; } void my_strcat(char s[], char t[]){ int i, j; for (i = 0; s[i] != '\0'; i++); for (j = 0; t[j] != '\0'; i++, j++){ s[i] = t[j]; } s[i] = '\0'; } }

  • C言語で、引数が構造体の場合

    生徒の名前、点数、順位を表示するプログラムをつくりたいのですが、(下のような関数を用いることを前提として) void rank1(struct data *x,int n) { int i,j; for(i=0;i<n;i++) x[i].rank=1; for(i=0;i<n;i++) for(j=0;j<n;j++) if(x[i].score<x[j].score) x[i].rank++; } このような場合、関数の引数として、構造体が用いられているわけですよね? 引数が構造体の場合、どのように引数の部分を書けばいいのか分かりません。 私が考えたプログラムは下記の通りです。 もちろんうまくいきませんでした。 たぶん最後のprintfの所のrank1の引数が間違っているだけだと思うんですが、どうでしょうか? include<stdio.h> struct data { char name; int score; int rank; }; void rank1(struct data *x,int n) { int i,j; for(i=0;i<n;i++) x[i].rank=1; for(i=0;i<n;i++) for(j=0;j<n;j++) if(x[i].score<x[j].score) x[i].rank++; } void main(void) { int m; static struct data x[] = {{'A',56,1}, {'B',79,1}, {'C',34,1}, {'D',91,1}, {'E',69,1}}; for(m=0;m<5;m++) printf("%c君 %d点 %d位\n",x[m].name,x[m].score,rank1(x,m)); }

  • サブ関数、メイン関数

    C言語の質問です! ランダムに九九の計算を出題して、キーボードから答えを入力し、正解かどうかを判定するプログラムをつくりたいです。出題の部分をサブ関数、判定の部分をメイン関数として作成する場合、どのようなプログラムの書き方になるのか、教えてください! #include<stdio.h> #include<stdlib.h> #include<process.h> void kakezan(void); void answer(void); void hanrei(void); int a,b,c; int main() { printf("やめるときは、100と入力してください。\n");   while(1){ kakezan(); answer(); hantei(); } return 0; } void kakezan(void) { a=rand() %10; b=rand() %10; printf("%d×%d=",a,b); } void answer(void) { scanf("%d",&c); if(c==100) exit(0); } void hantei(void) { if(c==a*b) printf(">>正解\n"); else printf(">>不正解\n"); printf("\n"); return; } 一応考えてみたのですが、 ちゃんと、判定→メイン  出題→サブ関数になっているのかなとおもって・・・   このプログラムであっているのでしょうか??

  • (マルチスレッド)_beginthreadexに複数の引数を渡す

    現在プログラムでマルチスレッドをやろうとしているのですが、 マルチスレッドの関数に数値や配列などの引数を渡すことは可能でしょうか? MSDNで調べてみると、_beginthreadex関数の4番目のNULLのところに引数リストを 指定できるとあったのですが、その意味が良くわかりませんでした。 以下のプログラムの場合にマルチスレッドに変数a, b, cを引数として渡したい場合は どのように書けばいいのでしょうか? #include <stdio.h> #include <windows.h> #include <process.h> unsigned WINAPI MyThread( void *lpx ){ while (1) { printf("スレッド実行中\n"); Sleep(1000); } return 0; } void main(){ // スレッドに渡したい変数の宣言 int a = 128; int b = 256; int c = 512; // スレッドIDの宣言 DWORD thID; // マルチスレッドの開始 (HANDLE)_beginthreadex( NULL, 0, &MyThread, NULL, 0, (unsigned int*)&thID ); // ループ while (1) { printf("メイン関数実行中\n"); Sleep(2000); } }

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • C言語で2次元配列の引数定義やコピーの仕方など

    2次元配列の引数の定義や渡し方や ある変換する関数で、すべて' '(スペース)にしたり[memmoveなど1命令で]や、 それぞれ一つ違う値 A->B, O->Pに置き変える関数しようとしているのですが、 C言語のデータ操作に非常に疎く、どのようにすれば良いかわかりません。 どのようにすれば良いのでしょうか? 環境はWindowsで VisualC++6.0です。 GCCもソースを変えずに同じように出来るのでしょうか? #include <stdio.h> char lesson[7][6] = { {'A', 'B', 'C', 'D', 'E', 'F'}, // MON {'G', 'H', 'I', 'J', 'K', 'L'}, // TUE {'M', 'N', 'O', 'P', 'Q', 'R'}, // WED {'S', 'T', 'U', 'V', 'W', 'X'}, // THU {'Y', 'Z', 'a', 'b', 'c', 'd'}, // FRI {'e', 'f', 'g', 'h', 'i', 'j'}, // SAT {'k', 'l', 'm', 'n', 'o', 'p'}, // SUN }; // --- 多次元配列の引数の渡し方がわからないのでvoid --- void print_data(void) { for(int i=0; i < 7; i++){ for(int j=0; j < 6; j++){ printf("%c ", lesson[i][j]); } printf("\n"); } } // --- 問題の変換関数(引数定義と内容 --- int convert(????) { ???? } // --- メイン --- int main(boid){ print_data(); conver(???); // <--- どのように引数に渡すのか? print_data(); return 0; }

  • 関数ポインタにvirtual関数を与えたいです

    //関数ポインタについて質問させてください。 //error C2440: '=' : 'void (__thiscall A::* )(int,int)' から 'void (__cdecl *)(int,int)' に変換できません。 //というエラーが出ます。 //どうすればいいのか教えてください。 //よろしくお願いします。 #include<stdio.h> class A { public: void (*aaa)(int a,int b); virtual void test(int a,int b)=0; virtual void test2(int a,int b)=0; void execute() { aaa=test;//error C2440 } }; class B : public A { public: void test(int a,int b) { printf("test"); } void test2(int a,int b) { printf("test2"); } }; int main() { B b; b.execute(); b.aaa(2,3); return 0; }

専門家に質問してみよう