• ベストアンサー

よく分からない関数?がある

プログラミングが良く分かっていないため、このプログラムを読みきる事ができませんでした。 #include <stdio.h> int (*get_sign)(); int iget_sign(int *a); int dget_sign(double *a); main(){ int sgn, idt=5; //intを2つ作成。idtは5 double fdt = -3.234; //ダブル型のfidを作成、数値は-3.234 get_sign = iget_sign; //不明:get_sigin sgn = get_sign(&idt); //get_siginにidtの数値を渡してsgnにいれてる printf("*date:%d sgn:%d\n",idt ,sgn); get_sign = dget_sign; sgn = get_sign(&fdt); printf("*data:%lf sgn:%d\n", fdt, sgn); } int iget_sign(int *a){ if(*a == 0) return 0; else if(*a > 0) return 1; else return -1; } int dget_sign(double *a){ if(*a == 0) return 0; else if(*a > 0.0) return 1; else return -1; } 数値が0なら0を、プラスなら1をマイナスなら-1を返すプログラムだと言うことは分かります。 しかし、2行目の「int (*get_sign)();」や10行目の「get_sign = iget_sign; //不明:get_sigin」が良く分かりません。 ぜひアドバイスをお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★アドバイス ・ポインタ変数には、変数が格納されている場所を指し示すものと  関数が格納されている場所を指し示すものの2つがあります。  今回は関数の場所を示すものとして get_sign という関数ポインタがあります。  この関数へのポインタは  int型用の iget_sign()  double型用の dget_sign()  の関数アドレスを保持します。 ・最初に『get_sign = iget_sign;』の行で関数ポインタ get_sign は iget_sign() 関数の  格納されている場所(アドレス)をセットします。その次の行で『sgn = get_sign(&idt);』  として呼び出すと iget_sign() 関数を呼び出したことになります。 ・次に『get_sign = dget_sign;』の行で関数ポインタ get_sign は dget_sign() 関数の  格納されている場所(アドレス)をセットします。だから次の行で『sgn = get_sign(&idt);』  として呼び出すと dget_sign() 関数を呼び出したことになるのです。 ・よって関数ポインタ get_sign の内容(関数へのアドレス)によって get_sign() 関数を  呼び出したとき iget_sign()か、dget_sign() のどちらの関数を呼び出すかが決定されます。  なお、関数ポインタを利用するには普通の変数へのポインタと同様に必ず初期化してから  使います。これをしないと実行時にどのような動作になるか分かりません。  また何も(関数へのポインタが)セットされていない場合には NULL としておけば  『if ( get_sign == NULL ) { エラー処理; }』とか、  『if ( get_sign != NULL ) { get_sign(引数); }』とか  することで安全対策が取れます。  ※今回は関数ポインタ get_sign がグローバル変数ですので明示的に NULL を  ※セットしなくても最初から get_sign に NULL が入っています。  ※ローカル変数の場合には注意して下さい。→自分で NULL とか入れて初期化。

nanacy01
質問者

お礼

丁寧な解説ありがとうございます。 おかげさまで理解する事が出来ました。

その他の回答 (2)

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.3

変数はメモリのどこかに格納されるのでアドレスを持つ、 ということはおわかりですね。 関数もまたしかりです。

nanacy01
質問者

お礼

関数もポインタが使えるんですね。 勉強になりました。ありがとうございます。

  • manima2
  • ベストアンサー率16% (11/66)
回答No.1

こんにちは。 「関数ポインタ」ってわかります? 調べてみてはどうでしょう。

nanacy01
質問者

お礼

関数にもポインタが使えるんですね。 知りませんでした。ありがとうございました。

関連するQ&A

  • 関数のアドレスをコピーすることについて

    ◎1--------------------------- #include<stdio.h> void (*putdata)(int d);  //// (1) //// void english(int dt); void japanese(int dt); int main( ) { int a=234; putdata=english; putdata(a); putdata=japanese; putdata(a); return 0; } void english(int dt) { printf("Value is %d.\n",dt); } void japanese(int dt) { printf("数値は%dです.\n",dt); } --------------------------------- ◎2-------------------------------- #include<stdio.h> int (*get_sign) ( ); //// (2) //// int iget_sign(int *a); int dget_sign(double *a); int main( ) { int sgn,idt=6; double fdt=-2.123; get_sign=iget_sign; sgn=get_sign(&idt); printf("data:%d sgn:%d\n",idt,sgn); get_sign=dget_sign; sgn=get_sign(&fdt); printf("data:%f sgn:%d\n",fdt,sgn); return 0; } int iget_sign(int *a) { if(*a==0) return 0; else if(*a>0) return 1; else return -1; } int dget_sign(double *a) { if(*a==0.0) return 0; else if(*a>0.0) return 1; else return -1; } --------------------------------- 以上2つのプログラムについて疑問があります。 ◎1の「putdata=english;」と関数のアドレスをコピーするにおいて、(1)の部分の引数の「(int d)」がどういう意味があるか分かりません。 次に◎2の(2)の部分で、「int (*get_sign) ( );」と引数を空にするというのが理解できません。本当は(2)の部分を、「int (*get_sign)(void *a);」 にしなくてはいけないと参考書に書いてあったのですが、何故そうしなくてはいけないかも理解できません。 C++で実行すると、チェックが厳しいということで、エラーが出てしまうというのは、参考書には書いてあったのですが、その前に(1)、(2)での関数プロトタイプの引数の表現方法が理解できません。 教えていただけると嬉しいです。

  • strtol関数をmalloc()関数を使用して次のソースプログラムを

    strtol関数をmalloc()関数を使用して次のソースプログラムを修正しなさいを言われました。 どなたか詳しい方よろしくお願いします。 #include <limits.h> #include <ctype.h> #include <errno.h> #include <stdio.h> int _space_sign(const char *s, const char **endptr); int _space_sign(const char *s, const char **endptr) { int sign ; while (isspace((unsigned char)*s)) ++s; sign = 0; switch (*s) { case '-': sign = -1; // fall through case '+': ++s; break; } *endptr = s; return sign; } long int strtolong(const char * s, char ** endptr, int base) { int c; int sign = _space_sign(s, (const char**)&s); long result; if (s[0] == '0') { ++s; if ((s[1] | 0x20) == 'x') { if (base == 0 || base == 16) { ++s; base = 16; } } else if (base == 0) base = 8; } else if (base == 0) base = 10; result = 0; for (; c = tolower((unsigned char)*s), isdigit(c) || ('a' <= c && c <= 'v'); s++) { int d ; if( isdigit(c) ) d= c - '0' ; else d = c - 'a' + 10; if (d >= base) break; if (result > (LONG_MAX - d - sign) / base) { errno = ERANGE; result = sign ? LONG_MIN : LONG_MAX; } else { result = result * base + d; } } if (endptr != NULL) *endptr = (char*)s; if (sign != 0) result = -result; return result; } int main(void) { char s[128], *e; long n; int base; printf("何進数で変換しますか。"); scanf("%d", &base); printf("変換する数値を入力してください。"); scanf("%s", s); n = strtolong(s, &e, base); if (errno != ERANGE) { printf("変換数値=%ld\n", n); if (*e != '\0') { printf("変換不可能部分=%s\n", e); printf("%d文字目の\'%c\'が変換不可\n", e-s+1, *e); } } else if (n == LONG_MAX) printf("long値で表現できる値を上回りました。\n"); else if (n == LONG_MIN) printf("long値で表現できる値を下回りました。\n"); return 0; }

  • 関数におけるif文とreturn文について

    ◎1-------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0) return; printf("%f の平方根=%f\n",n,sqrt(n)); } ----------------------------------------------- ◎2------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0){ return; printf("%f の平方根=%f\n",n,sqrt(n)); } } ----------------------------------------------- ◎3-------------------------------------------- #include<stdio.h> #include<math.h> double maxdt(double a,double b); void disp_sqrt(double n); int main(void) { double mx; mx=maxdt(22.33,44.55); printf("mx=%f\n",mx); disp_sqrt(3.0); disp_sqrt(-6.0); return 0; } double maxdt(double a,double b) { if(a>b) return a; else return b; } void disp_sqrt(double n) { if(n<=0.0){ return; } else{ printf("%f の平方根=%f\n",n,sqrt(n)); } } -------------------------------------------------- ◎1は参考書を参考に作ったものです。 ◎1は正常に動きます。 以上3つのプログラムで、疑問に思ったのは、関数「void disp_sqrt(double n);」についてなのですが、自分はif文が文が1つでもカッコ{ }を付けたい考えなので、◎1の「void disp_sqrt(double n)」の関数のif文に{}を付けようと思い、まず◎2のように変えたところ、平方根の表示が何も出ませんでした。 return文も文の1つだと考え、◎3のような形は正常に動きました。 return文とprintf文の2つの文があるという考えは間違っているのでしょうか? 後、◎1は何故{ }が無くてもよく、◎2は何も表示されないのでしょうか? 教えていただけると嬉しいです。

  • モジュール分割とユーザ関数

    c言語初心者です。 ユーザー関数を作って、下記のプログラムをどのようにモジュール分割すればいいと思いますか。教えてください。 //n進数の四則演算 #include <stdio.h> void main() { int ch; /* 入力文字ワーク */ int ntype = 0; /* n進数 */ int num1 = 0; /* 数値1 */ int op; /* 演算子 */ int num2 = 0; /* 数値2 */ int ans; /* 演算結果 */ printf("\nInput n(numeral type 2-16)\n"); while ((ch = getchar()) != '\n') { if (ch >= '0' && ch <= '9') { ntype = ntype * 10 + ch - '0'; } else { printf("Numeral type incorrect! 01\n"); return; } } if (ntype < 2 || ntype > 16) { printf("Numeral type incorrect! 02\n"); return; } printf("\nInput numeral1\n"); if ((ch = getchar()) == '\n') { printf("Numeral1 incorrect!\n"); return; } while (ch != '\n') { if (ntype <= 10) { if (ch >= '0' && ch <= '9' - (10 - ntype)) { num1 = num1 * ntype + ch - '0'; } else { printf("Numeral1 incorrect! 03\n"); return; } } else { if (ch >= '0' && ch <= '9') { num1 = num1 * ntype + ch - '0'; } else { if (ch >= 'a' && ch <= 'f' - (16 - ntype)) { num1 = num1 * ntype + ch - 'a' + 10; } else { printf("Numeral1 incorrect 04!\n"); return; } } } ch = getchar(); } printf("\nInput operator\n"); op = getchar(); if (op != '+' && op != '-' && op != '*' && op !='/') { printf("Operator incorrect! 05\n"); return; } if (getchar() != '\n') { printf("Operator incorrect! 06\n"); return; } printf("\nInput numeral2\n"); if ((ch = getchar()) == '\n') { printf("Numeral2 incorrect! 07\n"); return; } while (ch != '\n') { if (ntype <= 10) { if (ch >= '0' && ch <= '9' - (10 - ntype)) { num2 = num2 * ntype + ch - '0'; } else { printf("Numeral2 incorrect! 08\n"); return; } } else { if (ch >= '0' && ch <= '9') { num2 = num2 * ntype + ch - '0'; } else { if (ch >= 'a' && ch <= 'f' - (16 - ntype)) { num2 = num2 * ntype + ch - 'a' + 10; } else { printf("Numeral2 incorrect! 09\n"); return; } } } ch = getchar(); } switch (op) { case '+': ans = num1 + num2; break; case '-': ans = num1 - num2; break; case '*': ans = num1 * num2; break; case '/': if (num2 == 0) { printf("\nCan't divide by 0\n"); return; } ans = num1 / num2; } printf("\nThe answer is %d\n", ans); }

  • void型ポインタについて

    -------------------------------- #include<stdio.h> void uni_disp(void *p,int typ); int main() { int idt=123456; double ddt=56.789; char ss[]="abcdef"; uni_disp(&idt,'I'); uni_disp(&ddt,'D'); uni_disp(ss,'S'); uni_disp("STRING",'S'); return 0; } void uni_disp(void *p,int typ) { if(typ=='I'){ printf("%d\n",*(int *)p); } else if(typ=='D'){ printf("%f\n",*(double *)p); } else if(typ=='S'){ printf("%s\n",(char *)p); } } ----------------------------------- 以上のプログラム等で、void型ポインタをint型ポインタ、double型ポインタとみなす場合の、「*(int *)p」や「*(double *)p」の表記がどういう仕組みになっているか分かりません。 「*(int)p」などはエラーが出るのですが、やはり表記の意味を理解していないため何故か分かりません。 「*(int *)p」などの表記を分解して教えていただけると嬉しいです。

  • 分数を表示するプログラム(長文です)

    (整数値)aの値と(整数値)bの値をキーボードから入力して、そこから、a/bという分数を作るプログラムを書きたいと思います。(符号や約分も考えた形にする) 僕は、ヒントを参考に以下のようなプログラムを書いたのですが、ある条件の下では、正しく動きません。 ・aの値が負の場合 ・aもbも負の値の場合 など・・・ #include <stdio.h> #include <math.h> int main ( void ) { int a,b; int k,min,sign; printf("a=?");scanf("%d",&a); printf("b=?");scanf("%d",&b); if (a*b<0) sign = -1; else sign = 1; a = sign*a ; b = sign*b; if (abs(a)>abs(b)) min = b; else min = abs(a); for ( k=2 ; k<=min ; k++){ if (min%k == 0){ a = a/k; b = b/k; } } printf("a/b = %d",a); if (b != 1) printf("/%d\n",b); else printf("\n"); return 0; } これをどのように修正すれば、正確な答えが出るのでしょうか? 教えてください。

  • C言語初心者です。

    大学に入ってからC言語を授業で習い始めました。なので、すごい初歩的なことですが丁寧に教えてくださると嬉しいです。いくつか分からないことがあるので教えてください。   1・よくprintf("");なので%dや%fを使いますが、これはint(整数)の時が%dで、double(小数点付)の時に%fを使えばいいのか。 2・mul(呼び出す)、return(戻る)の意味、使い方 3・if(aaaa%4==0){ if(aaaa%100!=0)printf("閏年である。\n"); else{if(aaaa%400==0)printf("閏年である。\n"); else printf("閏年ではない。\n"); の意味は、もしaaaaが4で割り切れ、100で割り切れなかったら閏年で、そうではなく100で割り切れ400で割り切れたら閏年である。という意味でいいのか。 4・andとor,whileの使い方が分からない。 5・授業でやったことなのですが、 # include<studio.h>  int passWordInput(); main(){    int a, pw=1234, a=passWordInput(); if(a==pw)printf("ok\n"); else{a=passWordInput(); if(a==pw)printf("ok\n"); else{a=passWordInput(); if(a==pw)printf("ok\n"); else printf("Byw!!\n"); } } } int passWordInput(){ int wk; printf("パスワード:");scanf("%d",&wk); return wk; } がよく分かりませんでした。特にwkが出てくるあたりからです。 一応全て自分なりに本とか見てみましたが、あまり理解出来なかったので詳しい回答をしてくださると嬉しいです。よろしくお願いします。

  • 文法エラー

    { int a; int b; printf("正の整数:"); scanf("%d",&b); for(a%b ==0) { break; } printf("は素数",b); if(a == b) { printf("です。\n"); } else if { printf("でない。\n"); } return 0; } else if の前のところがエラーとして報告されます。 どこが間違っているのか解りません。 よろしくお願いします。

  • フローチャートについての質問です

    #include <stdio.h> int main(void) { int n1, n2, n3; printf ("数値1: "); scanf ("%d",&n1); if (n1%2==1){ printf ("数値1は奇数\n"); } else { printf ("数値1は偶数\n"); } printf ("数値2: "); scanf ("%d ",&n2); printf ("数値3: "); scanf ("%d",&n3); if (n2 > n3) printf ("数値2の方が数値3より大きい\n"); else if (n2 < n3) printf("数値2より数値3の方が大きい\n"); else printf("数値2と数値3は等しい\n"); return 0; } をフローチャートに直したいのですが方法が解りませんどなたか親切なかたお教えください JIS規格のものでお願いします

  • C言語の関数に関する質問ですが

    C言語の初心者です。よろしくお願いいたします。 授業でこのような演習が出ました。 演習:実数x を入力したときの最大値を求めるプログラムを作れ. 実数x を入力すると,x; -x; x2; xの絶対値の平方根 の中で一番大きい値を答える プログラムを作れ(ファイル名はmax.c とする). 表示は以下のようにする. Input x: -0.5 【Enter】 Answer is 0.707107. #include<stdio.h> #include<math.h> double max(double a, double b){ if( a > b) return a; else return b; } int main(void) { double x,y; printf(\"Input x: \"); scanf(\"%lf\",&x); y = max (x,-x); y = max (y,x*x); y = max (y,sqrt(fabs(x))); printf(\"Answer is %f.\\n\",y); } このように書けばうまく実行できますが、関数の中に関数を使えないでしょうか。うまく言えないですが、たとえば、以下のように書いてみましたが、うまく実行できません。どう直したらいいでしょうか、お忙しい中教えていただけたらうれしいです。 #include <stdio.h> #include <math.h> int max(double a,double b) { if (a<b) return b; else return a;} int main(void) { double x,result; printf(\"Input x:\"); scanf(\"%lf\",&x); result=max(max(x,-x),max(pow(x,2),sqrt(fabs(x)))); printf(\"%.2f\",result); return 0; } よろしくお願いいたします!!

専門家に質問してみよう