Getc() vs fgetc() - Каковы основные отличия?
Везде, где я вижу "это практически идентично", или что-то подобное...
Из Учебник по программированию GNU C:
В библиотеке GNU C есть еще одна функция, называемая fgetc. Он идентичен getc в большинстве случаев, за исключением того, что getc обычно реализуется как макрофункция и сильно оптимизирован, поэтому предпочтительнее в большинстве ситуаций. (В ситуациях, когда вы читаете со стандартного ввода, getc примерно так же быстро, как fgetc, поскольку люди печатают медленно по сравнению с тем, как быстрые компьютеры могут читать свои данные, но когда вы читаете из потока, который не интерактивно создается человеком, fgetc, вероятно, лучше.)
Каковы другие отличия? Я слышал, что у каждой из них есть другая реализация (и ее можно использовать как макрос), но что делает их soo разными (или достаточно разными) для них как в стандартной библиотеке C (или спецификации)?
Ответы
Ответ 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 являются реализациями свободного программного обеспечения. И теперь они могут быть реализованы как встроенные функции (такие же быстрые, как макросы).
И я не буду так беспокоиться. В реальной жизни операции ввода/вывода в основном ограничены аппаратными средствами (например, время доступа к диску).