Подтвердить что ты не робот

Getc() vs fgetc() - Каковы основные отличия?

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

Из Учебник по программированию GNU C:

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

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

4b9b3361

Ответ 1

Из Advanced Programming in Unix Environment:

...

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

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

...

Ответ 2

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

Одна точка, которая может иметь значение - Страница руководства говорит 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 безопасен в таких ситуациях.

Ответ 3

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

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