Odpovědí na tuto otázku je, že fflush(stream)
je formálně definován pouze pro výstupní proudy, takže fflush(stdout)
je v pořádku, ale fflush(stdin)
ne.
Účelem fflush(stream)
je, aby operační systém propláchl všechny buffery do základního souboru. Příklad legitimního použití: Studenti mají často problémy typu „nezobrazí se mi prompt!“, pokud udělají něco jako:
printf("Enter a number: ");
Zjistí však, že toto funguje dobře:
printf("Enter a number:\n");
Samozřejmě nechtějí, aby se za promptem objevil nový řádek, takže mají trochu problém.
Důvodem je to, že výstup do stdout
je vyrovnávací pamětí operačního systému a výchozí chování je (často) takové, že se výstup do terminálu skutečně zapíše až při výskytu nového řádku. Přidáním fflush(stdout)
za printf()
se problém vyřeší:
printf("Enter a number: ");fflush(stdout);
Nyní, když pracujeme analogicky, lidé si často myslí, že fflush(stdin)
by měl zahodit každý nepoužitý vstup, ale když se nad tím trochu zamyslíte, nedává to moc smysl. Co znamená „propláchnout“ vstupní vyrovnávací paměť? Kam se „proplachuje“? Pokud propláchnete výstupní buffer, výstup se odešle do základního souboru nebo terminálu, kde by nakonec stejně skončil, ale kde by vstup „nakonec stejně skončil“? To nemůžeme vědět! Jak by se měl chovat vstupní datový tok, který pochází ze souboru, roury nebo socketu? Pro vstupní proudy není vůbec jasné, jaké by mělo být chování fflush()
, ale pro výstupní proudy je to zcela jasné ve všech případech. Proto je fflush()
definováno pouze pro výstupní proudy.
Důvod, proč se chybné používání fflush(stdin)
stalo běžným, spočívá v tom, že před mnoha lety několik operačních systémů skutečně implementovalo schéma, v němž fungovalo tak, jak mnoho lidí očekávalo, a zahazovalo nepoužitý vstup. Dobrým příkladem je Microsoft DOS. Překvapivě i moderní verze Linuxu implementují fflush()
pro vstupní proudy.
Správná věc, kterou je třeba udělat s „přebytečným“ nechtěným vstupem terminálu, je prostě ho přečíst a nic s ním nedělat. Je to téměř stejně snadné jako volání fflush(stdin)
, funguje to všude a nespoléhá se to na formálně nedefinované chování.
Standard C říká:
Pokud stream ukazuje na výstupní nebo aktualizační stream, ve kterém poslední operace nebyla vstupní, funkce fflush způsobí, že všechna nezapsaná data pro tento stream budou dodána do hostitelského prostředí a zapsána do souboru; jinak je chování nedefinované.
POSIX říká (také explicitně odkazuje na standard C):
Ukazuje-li funkce fflush() na výstupní nebo aktualizační proud, v němž poslední operace nebyla vstupní, způsobí, že všechna nezapsaná data pro tento proud budou zapsána do souboru, ….
Ale manuálová stránka Linuxu říká:
Pro výstupní proudy si fflush() vynutí zápis všech dat uložených v uživatelské vyrovnávací paměti pro daný výstupní nebo aktualizační proud prostřednictvím základní funkce zápisu tohoto proudu. U vstupních toků funkce fflush() zahodí všechna data ve vyrovnávací paměti, která byla načtena z podkladového souboru, ale nebyla spotřebována aplikací. Stav otevřeného proudu není ovlivněn.