2013-08-28 13 views
38

Wszędzie widzę "jest praktycznie identyczne", lub coś podobnego ...getc() vs fgetc() - Jakie są główne różnice?

Od The GNU C Programming Tutorial:

Jest jeszcze inna funkcja w bibliotece C GNU nazywa fgetc. Jest to identyczne z getc pod wieloma względami, z tym wyjątkiem, że getc jest zwykle zaimplementowany jako funkcja makro i jest wysoce zoptymalizowany, więc jest preferowany w większości sytuacji. (W sytuacjach, w których czytasz ze standardowego wejścia, getc jest tak szybki jak fgetc, ponieważ ludzie wpisują powoli w porównaniu do tego, jak szybko komputery mogą odczytać swój wkład, ale kiedy czytasz ze strumienia, który nie jest interaktywnie wytwarzany przez człowieka, fgetc jest prawdopodobnie lepszy.)

Jakie są pozostałe różnice? Słyszałem, że każdy z nich ma inną implementację (i można go użyć jako makro), ale co sprawia, że ​​są one tak różne (lub wystarczająco różne), aby mogły znajdować się zarówno w bibliotece standardowej C (lub specyfikacji)?

+1

Dobre informacje tutaj: http://stackoverflow.com/questions/5186457/c-fgets-versus-fgetc-for-reading-line – dcaswell

+3

@ user814064, Twój link odwołał się 'fgets' kontra' fgetc', OP pyta o 'getc' vs' fgetc' –

+0

getc() jest wymieniany przy tym łączu, a także jego zaletach. – dcaswell

Odpowiedz

38

Z Advanced Programming in Unix Environment:

...

Różnica między getc i fgetc że getc może być zaimplementowane jako makro, natomiast fgetc nie mogą być realizowane jako makro. Oznacza to trzy rzeczy:

  • Argument do getc nie powinien być wyrażeniem z efektami ubocznymi.
  • Ponieważ fgetc ma zagwarantowaną funkcję, możemy wziąć jego adres. To pozwala nam przekazać adres fgetc jako argumentowi do innej funkcji.
  • Połączenia z fgetc prawdopodobnie trwają dłużej niż połączenia z numerem getc, ponieważ zwykle wymaga więcej czasu na wywołanie funkcji.

...

+0

I do +1, ale: dlaczego oba są w bibliotece standardowej? dlaczego nie może być makro? –

+1

Więc w jaki sposób 'getc' jest zdefiniowany jako makro? Jakikolwiek wskaźnik do tego? – day

+0

@day masz na myśli "jak" jak w "jakie są szczegóły implementacji" lub "jak możesz to zrobić (moralnie lub technicznie)"? –

2

Są zasadniczo takie same (lub podobne, aby nie przeszkadzały). Powinieneś spojrzeć na ich implementację: GNU libc i MUSL libc są implementacjami wolnego oprogramowania. I mogą być teraz zaimplementowane jako funkcje inline (które są tak szybkie, jak makra).

I nie będę się tak przejmował. W rzeczywistości, we/wy są w większości ograniczone przez sprzęt (np. Czas dostępu do dysku).

13

wydaje się, że różnice są w 99,9% przypadków, bez znaczenia.

Jeden punkt, który może mieć znaczenie - The man page mówi getc() may be implemented as a macro which evaluates stream more than once.

To może spowodować dziwne zachowanie w niektórych (nie bardzo przydatne) przypadkach, np .:

FILE *my_files[10] = {...}, *f=&my_files[0]; 
for (i=0; i<10; i++) { 
    int c = getc(f++); // Parameter to getc has side effects! 
} 

Jeśli getc ocenia f++ więcej niż raz, to będzie postęp f więcej niż raz na iteracji.Dla porównania, fgetc jest bezpieczny w takich sytuacjach.