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

Везде вижу "практически идентичный" или что-то подобное ...

Из Руководства по программированию GNU C:

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

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


person Joe DF    schedule 28.08.2013    source источник
comment
Здесь полезная информация: stackoverflow.com / questions / 5186457 /   -  person dcaswell    schedule 28.08.2013
comment
@ user814064, ваша ссылка ссылается на fgets vs fgetc, OP спрашивает о getc vs fgetc   -  person David Ranieri    schedule 28.08.2013
comment
По этой ссылке упоминается getc (), а также его преимущества.   -  person dcaswell    schedule 28.08.2013
comment
@ user814064, вы можете напрямую перейти к ответу (нажав поделиться) stackoverflow.com/a/5186605 / 1606345   -  person David Ranieri    schedule 28.08.2013
comment
Большое спасибо. Я публикую меньше недели, и мне нужно многому научиться. Я думал, что это FaceBook или что-то в этом роде.   -  person dcaswell    schedule 28.08.2013


Ответы (3)


Из Advanced Programming in Unix Environment:

...

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

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

...

person mohit    schedule 28.08.2013
comment
Я получил +1, но: почему они оба в стандартной библиотеке? почему оба не могут быть макросом? - person Joe DF; 28.08.2013
comment
@day вы имеете в виду, как в деталях реализации или как вы можете это сделать (морально или технически)? - person Peter - Reinstate Monica; 16.01.2015

Кажется, что различия в 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 безопасен в таких ситуациях.

person ugoren    schedule 28.08.2013

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

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

person Basile Starynkevitch    schedule 28.08.2013