[Subject Prev][Subject Next][Thread Prev][Thread Next][Subject Index][Thread Index]

Re: getc() and fgetc()



Disillusioned forced the electrons to say:
> I could not understand the difference between getc() and fgetc(). Similarily
> the difference between putc() and fputc().

getc() and fgetc() are equivalent in usage. Similar for putc() and fputc().

> the text says that the former can be implemented as a macro, now what does
> that mean?

That is the essential difference. This means that stdio.h might implement
getc() as a macro, so taking its address is not portable. If you need a
pointer to a function that takes one argument of type FILE * and returns
an int (;-), then you cannot portably use getc(), you will have to use
fgetc() which is guaranteed to be a function.

So, this is not portable:

int (*func)(FILE *) = getc;

whereas this is:

int (*func)(FILE *) = fgetc;

[Note: This difference also comes in if you dlopen() libc and try to
locate getc() and fgetc() in there via dlsym()].

Another difference is that getc() might evaluate its argument multiple
times, so if you have an array of FILE * pointers, then code like this
to read one character from each of them is bad:

FILE **arr; /* array [10] of FILE * pointers */
int i = 0, c[10];
while (i < 10) {
   c[i++] = getc(*arr++);
}

(Horrible, but you get the idea)

Whereas it is perfectly alright to use fgetc() in the above.

Here is an implementation of getc() (from /usr/lib/bcc/include/stdio.h) that
exhibits all the above points:

#define getc(stream) \
  (((stream)->bufpos >= (stream)->bufread) ? fgetc(stream): \
    (*(stream)->bufpos++))

This evaluates stream thrice.

Binand