2010-09-16 9 views
16

Sezione 7.9.13/7 di c99 afferma che:La linea stdout è bufferizzata, non bufferizzata o indeterminata per impostazione predefinita?

Al programma di start-up, tre flussi di testo sono predefiniti e non devono essere aperti in modo esplicito - standard input (per la lettura di ingresso convenzionali), standard output (per la scrittura di uscita convenzionale) e errore standard (per la scrittura dell'output diagnostico).

Come inizialmente aperto, il flusso di errore standard non è completamente bufferizzato; gli stream standard di input e output standard sono completamente bufferizzati se e solo se è possibile determinare il flusso in modo che non faccia riferimento a un dispositivo interattivo.

Quindi ha senso. Se stai spingendo il tuo output standard su un file, lo vuoi completamente bufferizzato per l'efficienza.

Ma non riesco a trovare nello standard se l'uscita è bufferizzata o non bufferizzata quando non è possibile impostare per determinare se il dispositivo non è interattivo (ovvero, output normale a un terminale).

Il motivo che mi chiedo è un commento alla mia risposta here che dovrei inserire un fflush(stdout); tra le due affermazioni:

printf ("Enter number> "); 
// fflush (stdout); needed ? 
if (fgets (buff, sizeof(buff), stdin) == NULL) { ... } 

perché non è stato terminato il printf con una nuova riga. Qualcuno può chiarirlo?

risposta

26

Lo standard C99 non specifica se i tre flussi standard sono senza buffer o con buffer di linea: È in corso l'implementazione. Tutte le implementazioni UNIX che conosco hanno una linea bufferizzata stdin. Su Linux, stdout nella linea bufferizzata e stderr senza buffer.

Per quanto ne so, POSIX non impone ulteriori restrizioni. La pagina di POSIX fflush fa nota nella sezione ESEMPI:

[...] La funzione fflush() viene utilizzato perché standard output viene generalmente tamponata e il messaggio non può essere immediatamente stampato sull'uscita o terminale.

Quindi l'osservazione che si aggiunge fflush(stdout); è corretta.


Un'alternativa potrebbe essere quella di rendere stdout senza buffer:

setbuf(stdout, NULL); 
/* or */ 
setvbuf(stdout, NULL, _IONBF, 0); 

Ma come osserva R. si può fare solo una volta, e deve essere prima di scrivere stdout o eseguire qualsiasi altra operantion su esso. (C99 7.19.5.5 2)


Ho appena letto un recent thread sul comp.lang.c circa la stessa cosa.Una delle osservazioni:

convenzione Unix è che stdin e stdout sono linea tamponata quando associato ad un terminale, e completamente tamponata (alias block-bufferizzato) altrimenti. stderr è sempre senza buffer.

+0

Non è possibile "temporaneamente" rendere "stdout' unbuffered. 'setbuf' e' setvbuf' hanno un comportamento indefinito a meno che non siano la prima operazione eseguita sul file dopo l'apertura. –

+0

@R ..: Grazie, hai ragione. Ho aggiunto questo alla risposta. – schot

+0

Nel caso del buffering di linea, c'è una filigrana alta dove, se la linea diventa troppo lunga, verrà svuotata? – CMCDragonkai