getc () vs fgetc () - в чем основные различия?

везде, где я вижу "это практически идентично", или что-то подобное...

с учебник по программированию GNU C :

в библиотеке GNU C есть еще одна функция, называемая fgetc. Он идентичен getc во многих отношениях, за исключением того, что getc обычно реализуется как макрофункция и сильно оптимизирован, поэтому предпочтительнее в большинстве ситуаций. (В ситуациях, когда вы читаете со стандартного ввода, getc примерно так же быстро, как fgetc, поскольку люди печатают медленно по сравнению с тем, как быстро компьютеры могут читать их ввод, но когда вы читаете из потока, который не интерактивно производится человеком, fgetc, вероятно, лучше.)

каковы другие различия? Я слышал, что у каждого из них есть другая реализация (и ее можно использовать как макрос), но что делает их настолько разными (или достаточно разными), чтобы они были в стандартной библиотеке C (или спецификации)?

3 ответов


С Advanced Programming in Unix Environment:

...

разницу между getc и fgetc это getc может быть реализован как макрос, тогда как fgetc не может быть реализован как макрос. Это означает три вещи:--10-->

  • аргумент getc не должно быть выражением с побочными эффектами.
  • С fgetc гарантированно будет функцией, мы можем взять ее адрес. Это позволяет нам передать адрес fgetc в качестве аргумента другой функции.
  • вызовы fgetc, вероятно, занимают больше времени, чем вызовы getc, так как обычно требуется больше времени для вызова функции.

...


похоже, что различия в 99,9% случаев бессмысленны.

один момент, который может иметь значение - man page говорит 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!
}

если getc оценивает f++ более одного раза, он будет продвигать f более одного раза за итерацию. Для сравнения,fgetc безопасно в таких ситуациях.


есть по существу то же самое (или достаточно похожее, чтобы не беспокоиться). Вы должны посмотреть на их реализацию:GNU libc и MUSL библиотеки libc являются реализациями свободного программного обеспечения. И теперь они могут быть реализованы как встроенные функции (которые так же быстры, как макросы).

и я не буду так сильно беспокоиться. В реальной жизни ввод-вывод в основном ограничен оборудованием (например, временем доступа к диску).