getc() vs fgetc() - What are the major differences?
Asked Answered
M

3

59

Everywhere I see "it is practically identical", or something similar...

From The GNU C Programming Tutorial :

There is another function in the GNU C Library called fgetc. It is identical to getc in most respects, except that getc is usually implemented as a macro function and is highly optimised, so is preferable in most situations. (In situations where you are reading from standard input, getc is about as fast as fgetc, since humans type slowly compared to how fast computers can read their input, but when you are reading from a stream that is not interactively produced by a human, fgetc is probably better.)

What are the other differences? I have heard that they each have a different implementation (and one can be used as a macro) but, what makes them soo different (or different enough) for them to be both in the Standard C library (or specification)?

Morgun answered 28/8, 2013 at 6:40 Comment(5)
Good info here: #5186957Yocum
@user814064, your link refered fgets vs fgetc, OP is asking about getc vs fgetcInterrupted
getc() is mentioned at that link, as well as its advantages.Yocum
@user814064, you can link directly to the answer (by clicking on share) https://mcmap.net/q/331188/-c-fgets-versus-fgetc-for-reading-lineInterrupted
Thank you so much. I've been posting for less than a week and I have a LOT to learn. I thought that was FaceBook or something.Yocum
L
59

From the Advanced Programming in Unix Environment:

...

The difference between getc and fgetc is that getc can be implemented as a macro, whereas fgetc cannot be implemented as a macro. This means three things:

  • The argument to getc should not be an expression with side effects.
  • Since fgetc is guaranteed to be a function, we can take its address. This allows us to pass the address of fgetc as an argument to another function.
  • Calls to fgetc probably take longer than calls to getc, as it usually takes more time to call a function.

...

Lumumba answered 28/8, 2013 at 6:48 Comment(4)
I up +1, but : why have Both of them in the Standard library? why cant both be a macro?Morgun
@day you mean "how" as in "what's the implementation details" or in "how can you do that (morally or technically)"?Bewick
@JoeDF — Why both? The most basic of reasons: backwards compatibility. The original standard I/O package had both — the C standard adopted both for backwards compatibility (to avoid breaking existing, working code). Note that if you #undef getc, there must be a function available in the library, even if it is normally a macro. Also, these days, with multi-threading and locks, etc, the performance benefit of the macro implementation is more debatable (but it depends on how the necessary locking is implemented).Calciferol
Wrong. fgetc can be implemented as a macro but cannot evalute its argument than once. Note that it also must be implemented as a function (on implementations where it is a macro it is actually both).Armyn
D
24

Seems like the differences are, in 99.9% of the cases, meaningless.

One point which may make a difference - The man page says getc() may be implemented as a macro which evaluates stream more than once.

It could lead to strange behavior in some (not very useful) cases, e.g.:

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

If getc evaluates f++ more than once, it will advance f more than once per iteration. In comparison, fgetc is safe in such situations.

Diaphony answered 28/8, 2013 at 7:26 Comment(0)
O
3

There are essentially the same (or similar enough to not bother). You should look at their implementation: GNU libc and MUSL libc are free software implementations. And they now could be implemented as inline functions (which are as fast as macros).

And I won't bother that much. In real life, I/O is mostly constrained by hardware (e.g. the time to access the disk).

Obel answered 28/8, 2013 at 6:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.