- ベストアンサー
C言語の関数ポインタとは?
- C言語における関数ポインタとは、関数へのポインタを指す変数のことです。
- 関数ポインタは、関数へのポインタを格納し、その関数を呼び出すことができます。
- また、関数ポインタを使用することで、プログラムの柔軟性を高めることができます。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
これは関数ポインタではなくて、関数のプロトタイプ宣言ですね。プロトタイプ宣言では、関数がどのような引数をとり、どのような返り値を返すかというのを記述します。 char *rindex(const char*s,int c); /*末尾から文字列検索*/ void hexdump(void); はconst char*型の引数とint型の引数を取って、char*型を返すrindexという関数と何も引数をとらず何も返さないhexdumpという関数を定義しています。こうすることでmain関数の中でこれらの関数が使われた場合に正しく型を認識することができるようになっています。 今回、main関数の中でおそらくrindex関数とhexdump関数が使われているのでこのように宣言しているのではないでしょうか。 プロトタイプ宣言の有効範囲 (スコープ) をmain関数の中に限定するのは無意味なので、プロトタイプ宣言は#includeの直後などに書かれるのが普通だと思いますけどね。 ちなみに、rindexはstrings.hに定義されているので#include <stdio.h>のあとに#include <strings.h>と書けばこんな変なことはしないでいいです。また、void hexdump(void);もusage関数の次の行に普通は書くものだと思います。 個人的にはこのプログラムをメンテナンスするくらいなら書き直します。プロトタイプ宣言をmain関数の中と外(usage関数)に分けるなど、なぞなプログラミングスタイルをしてくれています。また、hexdump関数が引数をとらずにFILE *fpin; /*file pointer*/をグローバルで宣言するというのも嫌ですね。グローバル変数を使っている関数はその関数の再利用性が著しく損なわれるので、理由がないとこの実装はしません。あと、stdlib.hをincludeしているわけですから#define ERR -1 /*system call error*/はいらないのではないかと予想します。
その他の回答 (4)
- 和泉 博(@hiroshi09s)
- ベストアンサー率54% (59/109)
stdlib.hに定義されているエラーの EXIT_FAILURE を無視する「#define ERR -1」とか http://www.geocities.jp/ky_webid/c/065.html strings.hに定義されている文字列sの中に,文字列tが最後に現れる位置を返す char *rindex(const char*s,int c); を「末尾から文字列検索」するといった受け狙い(?)の関数プロトタイプ宣言とか http://www.obihiro.ac.jp/~suzukim/masuda/octave/html/octave_28.html プロトタイプ宣言は、以前のCがint型関数は型名を明記しない慣習からバグが入り易い欠陥があり、事前にCコンパイラに知らせて誤りを検出する機能を強化するために設定された経緯を無視した main()関数内での書法解説とか http://ja.wikipedia.org/wiki/%E9%96%A2%E6%95%B0%E3%83%97%E3%83%AD%E3%83%88%E3%82%BF%E3%82%A4%E3%83%97 たかが、ファイル内のデータを16進表示するのに、FILE *fpin; はおろか main(int argc,char *argv[ ]){ と引数まで取り込む複雑なプログラミング内容と想像できる初心者向け入門書である(?)とか UNIX哲学を無視したC言語プログラミング入門書には、非常に興味があります。 http://en.wikipedia.org/wiki/Unix_philosophy 書籍名と著者を教えていただけませんか。 ちなみに、UNIXにおけるファイルの16進表示プログラムは↓のように簡単です。 使い方は UNIX哲学に習い、フィルターとしての機能を有し、次のようにコマンドラインを打ち込みます。 1.antis.c ソースファイルを 16進表示する。 ./a.out<antic.c 2.意味はないけどパイプを使う。 cat<antis.c | ./a.out /* Gcc on MacOSX * Source file name: antis.c */ #include <stdio.h> int main(void) { int c,count,offset,buf[3]; count=offset=0; printf("00000 "); while((c=getchar())!=EOF){ if(offset==0) { buf[1]=c; offset=1; }else{ buf[0]=c; printf("%02x%02x ",buf[0],buf[1]); offset=0; } count++; if(count%16==0) { printf("\n"); printf("%05x ",count); } } if(offset!=0) printf("%02x%02x ",0,buf[1]); printf("\n"); return 0; }
お礼
ご回答ありがとうございました。 ご提示いただいたサンプルソースコードもわかりやすくて助かります。 今参考にしている書籍は河野清尊氏の「C言語によるUNIXシステムプログラミング入門」という書籍です。
- KAZUMI2003
- ベストアンサー率37% (77/208)
No.1のものです。 あのままでは、分かりづらいと思ったので、補足。 関数のポインタは、次のように宣言します。 char (*function_name)(parameter_list); 最初のカッコにより、function_nameは、ポインタであり、次のカッコが付くことにより、それが関数であり、型名によって、その評価結果(この場合関数の戻り値)がcharである。 となります。 parameter_listは、普通の関数宣言時と同じ。 使い方はこんな感じ。 #include <stdio.h> void hello(void){ printf("hello\n"); } int main(){ void (*function_name)(void); function_name=hello; (*function_name)(); printf("こっちはメイン\n"); }
お礼
ご回答ありがとう御座います。 1度目の投稿に加え、ソースコードまでご提示いただきありがとうございました。 関数ポインタの挙動について理解する事ができました。 ありがとうございました。
- koi1234
- ベストアンサー率53% (1866/3459)
全体がわからないので嘘言ってたらすいません >usageメソッドはmain関数の外であるのに、rindexとhexdumpは何故main関数の中で宣言されているのでしょうか。 メソッドというか関数ですね 基本的にはどちらで宣言しても問題はありませんが あえて分けられているのであれば そういつソース内の他の関数があってそちらでも(複数個所で) usage を使ってる rindexとhexdumpは main関数内でしか使わない ということなのかもしれません >関数までのポインタを返す 違います この言い方が適切か分かりませんが rindex 関数が charのデータ格納領域のアドレス(char *)を返す ということを意味します 関数までのポインタを返すわけではありません 例えば 文字列 abcde がアドレス 100番地から順番にセットされていたとして rindex を 使う事により aの位置を検索する様な場合 アドレス 100 が返り bの位置を検索する様な場合 アドレス 101 が返り 以後 同様 といったような関数の仕様になっているということです (実際の処理内容に合わせていません あくまでイメージ) voidに関しては有効な値がない事を意味します
お礼
ご回答頂きありがとう御座います。 rindexの挙動について理解する事ができました。 おっしゃる通り、main関数内でのみ利用している関数だったため、main内で宣言していたようです。 ありがとうございました。
- KAZUMI2003
- ベストアンサー率37% (77/208)
関数の宣言は、 記憶クラス 型名 関数名(パラメータ宣言) ですので、 char *が、charへのポインタ型と解釈されます。つまり、この関数はcharへのポインタを返す関数だということです。多分、末尾から検索して、見つけた文字へのポインタでも返す仕様なのでしょう。 また、関数のプロトタイプも、変数と同じように、宣言した場所によって、スコープルール(その名前の有効範囲)が制限されます。 つまり、rindexという関数は、main内でしか使えないはずです。 しかし、標準のCでは、関数は入れ子に定義できないので、あまり意味はないと思います。
お礼
ご回答ありがとうございました。 プロトタイプ宣言は、mainの外で行うものと決めつけていた為、混乱していました。 グローバル変数ときくと、いろいろな箇所から自由に扱えるように思えるのですが、再利用性が失われるというのはどういったシーンでしょうか。