2014-08-28 9 views
7

Ultimamente, ho notato uno strano caso desidero verificare:caratteri scritti finora snprintf

da SUS, per %n in una stringa di formato, il rispettivo int sarà impostato al-quantità-di-byte -Esame scritto-to-the-uscita. Inoltre, per snprintf(dest, 3, "abcd"), dest punterà a "ab\0". Perché? Perché non devono essere scritti più di n (n = 3) byte nell'output (il buffer dest).

ho dedotto che per il codice:

int written; 
char dest[3]; 
snprintf(dest, 3, "abcde%n", &written); 

written sarà impostato su 2 (cessazione nulla escluso dal conteggio). Ma da un test che ho effettuato utilizzando GCC 4.8.1, written era impostato su 5. Stavo interpretando male lo standard? E 'un errore? È un comportamento indefinito?

Edit:

@wildplasser detto:

... il comportamento di% n nella stringa di formato potrebbe essere definito o implementazione definito ...

E

... l'implementazione deve simulare l'elaborazione della stringa di formato completa (compreso il% n) ...

@par detto:

written è 5 perché questo è il numero di caratteri si sarebbe scritto nel punto si incontra l'%n. Questo è un comportamento corretto. snprintf solo copie fino a size caratteri meno il nulla finale ...

E:

Un altro modo di guardare a questo è che il %n non sarebbero nemmeno stati riscontrati se trattati solo fino a 2 caratteri, quindi è pensabile aspettarsi written di avere un valore non valido ...

E:

... l'intera stringa è trasformati tramite printf() regole, poi viene applicata la massima lunghezza ...

Può essere verificata essere lo standard, uno standard di correnti o di qualche fonte ufficiale?

+0

Mi sembra un errore (nell'implementazione della libreria). – pmg

+1

Mi aspetto che dovresti * prima * guardare il valore di ritorno da snprintf(). Gli "effetti collaterali" sono diversi; il comportamento di '% n' nella stringa di formato potrebbe essere indefinito o definito dall'implementazione se il valore di ritorno è> = il secondo argomento. In ogni caso, l'implementazione deve * simulare * l'elaborazione della stringa di formato * complete * (incluso '% n') per ottenere il valore di ritorno corretto, in modo che l'effetto collaterale possa essere ottenuto al volo. – wildplasser

risposta

7

written è 5 perché è il numero di caratteri da scrivere nel punto in cui viene rilevato lo %n. Questo è un comportamento corretto. snprintf copia solo fino a size caratteri meno il punto finale null (quindi nel tuo caso 3-1 == 2. Devi separare il comportamento di formattazione della stringa dai caratteri solo-scrittura-così-molti.

Un altro modo per osservare questo è che il %n non sarebbe stato nemmeno incontrato se elaborasse solo fino a 2 caratteri, quindi è ipotizzabile aspettarsi che written abbia un valore non valido. Ecco dove ci sarebbe un bug, se ti aspettavi qualcosa di valido in written al punto %n incontrato (e non c'era).

Pertanto, l'intera stringa viene elaborata tramite le regole printf(), quindi viene applicata la lunghezza massima.

+1

Hmmm, il testo dello standard contiene ** "... numero di caratteri scritti nel flusso di output finora ..." **; ''c'','' d''e' 'e'' non sono stati scritti nel flusso di output – pmg

+1

@pmg - I caratteri * sono * scritti nel flusso di output, nella misura in cui il flusso di output è un buffer di dati " dietro le quinte "nella funzione printf(). * Quindi * si verifica il comportamento di snprintf della sola copia di caratteri della dimensione dal "flusso di output". Vedi la risposta di Heinz per un riferimento a ISOC99. – par

+1

poi di nuovo, forse il testo che si riferisce a ""% n "' non si applica a 'sprintf()' perché questa funzione non scrive sugli stream di output. – pmg

5

non è un bug: ISOC99 dice

La funzione snprintf è equivalente a fprintf [...] personaggi di uscita al di là della n-1 ° vengono scartati anziché scritto alla matrice [ ...]

Quindi, semplicemente scarta l'output finale ma si comporta diversamente.

Problemi correlati