web-dev-qa-db-ja.com

getc()vs fgetc()-主な違いは何ですか?

どこでも「実質的に同一」または似たようなものが表示されます...

から GNU Cプログラミングチュートリアル

GNU Cライブラリにはfgetcと呼ばれる別の関数があります。getcは通常マクロ関数として実装され、非常に最適化されているため、ほとんどの点でgetcと同じです。 (標準入力から読み取る場合は、コンピューターが入力を読み取る速度と比較して人間がゆっくり入力するため、getcはfgetcとほぼ同じ速度ですが、対話形式で生成されないストリームから読み取る場合は人間、fgetcのほうがおそらく良いでしょう。)

他の違いは何ですか?それらはそれぞれ異なる実装(およびマクロとして使用可能)を持っていると聞いたことがありますが、それらが標準Cライブラリ(または仕様)の両方に存在するためにそれらをまったく異なる(または十分に異なる)ものにしているのはなぜですか?

45
Joe DF

から Advanced Programming in Unix Environment

...

getcfgetcの違いは、getcをマクロとして実装できるのに対し、fgetcはマクロとして実装できないことです。これは3つのことを意味します。

  • getcの引数は、副作用のある式であってはなりません。
  • fgetcは関数であることが保証されているため、そのアドレスを取得できます。これにより、fgetcのアドレスを引数として別の関数に渡すことができます。
  • Fgetcの呼び出しは、おそらく関数の呼び出しに時間がかかるため、getcの呼び出しよりも時間がかかる可能性があります。

...

42
mohit

違いは、99.9%のケースで、意味がないようです。

違いを生む可能性のある1つのポイント- manページgetc() may be implemented as a macro which evaluates stream more than onceと言います。

いくつかの(あまり役に立たない)場合に奇妙な動作を引き起こす可能性があります:

FILE *my_files[10] = {...}, *f=&my_files[0];
for (i=0; i<10; i++) {
    int c = getc(f++);    // Parameter to getc has side effects!
}

getcf++を複数回評価する場合、反復ごとにfを複数回進めます。それに対して、fgetcはそのような状況では安全です。

17
ugoren

基本的に同じ(または気にしないほど十分に似ています)があります。それらの実装を見てください: GNU libc および MUSL libc はフリーソフトウェア実装です。そして、それらはインライン関数(マクロと同じくらい高速)として実装できるようになりました。

そして、私はそれほど気にしません。実際には、I/Oはハードウェア(ディスクへのアクセス時間など)によってほとんど制約されます。