Svaret på detta är att fflush(stream)
endast är formellt definierat för utdataströmmar, så fflush(stdout)
är OK, men fflush(stdin)
är det inte.
Syftet med fflush(stream)
är att få operativsystemet att spola alla buffertar till den underliggande filen. Som exempel på en legitim användning kan nämnas att studenter ofta har problem som ”min prompt visas inte!” om de gör något som:
printf("Enter a number: ");
Hur som helst upptäcker de att detta fungerar utmärkt:
printf("Enter a number:\n");
Självklart vill de inte ha en nyrad efter sin prompt, så de har ett litet problem.
Anledningen till detta är att utmatningen till stdout
buffras av operativsystemet och standardbeteendet är (ofta) bara att faktiskt skriva utmatningen till terminalen när en ny rad påträffas. Att lägga till en fflush(stdout)
efter printf()
löser problemet:
printf("Enter a number: ");fflush(stdout);
Nu, genom att arbeta analogt, tror folk ofta att fflush(stdin)
ska kassera alla oanvända inmatningar, men om man tänker efter lite grann så är det inte särskilt vettigt. Vad innebär det att ”spola” en inmatningsbuffert? Vart ”spolas” den till? Om du spolar en utdatapuffer skickas utdata till den underliggande filen eller terminalen, där den så småningom skulle hamna ändå, men var skulle input ”så småningom hamna ändå”? Det finns inget sätt att veta! Hur ska beteendet vara om inmatningsdata kommer från en fil, en pipe eller en socket? Det är inte alls klart för inmatningsströmmar vad beteendet för fflush()
ska vara, men det är mycket klart för utmatningsströmmar i alla fall. Därför definieras fflush()
endast för utdataströmmar.
Anledningen till att den felaktiga användningen av fflush(stdin)
blev vanlig är att några operativsystem för många år sedan implementerade ett system där det fungerade som många förväntade sig, att oanvända indata kasserades. Microsoft DOS är ett bra exempel. Överraskande nog implementerar moderna versioner av Linux också fflush()
för inmatningsströmmar.
Det rätta att göra med ”extra” oönskad terminalinmatning är helt enkelt att läsa den och inte göra något med den. Detta är nästan lika enkelt som att kalla fflush(stdin)
, fungerar överallt och förlitar sig inte på ett formellt odefinierat beteende.
C-standarden säger:
Om stream pekar på en utdataström eller en uppdateringsström där den senaste operationen inte var en inmatning, så får fflush-funktionen alla oskrivna data för den strömmen som ska levereras till värddatormiljön att skrivas till filen; annars är beteendet odefinierat.
POSIX säger (hänvisar också uttryckligen till C-standarden):
Om stream pekar på en utdataström eller en uppdateringsström där den senaste operationen inte var inmatning, ska fflush() orsaka att oskrivna data för den strömmen skrivs till filen, …
Men på Linux manpage står det:
För utdataströmmar tvingar fflush() fram en skrivning av all buffrad data i användarutrymmet för den givna utdataströmmen eller uppdateringsströmmen via strömmens underliggande skrivfunktion. För inmatningsströmmar kastar fflush() alla buffrade data som har hämtats från den underliggande filen, men som inte har konsumerats av programmet. Strömens öppna status påverkas inte.