2011-12-14 6 views
27

Background: ho un numero di script che analizzano i file di registro alla ricerca di numeri esadecimali trovando il "0x" iniziale. La nostra libreria C incorporata è stata modificata in una nuova printf. Il nuovo printf è più conforme agli standard rispetto al nostro precedente e i miei script si sono interrotti.Perché 0 (zero) viene stampato senza "0x" iniziale con C printf formato "% # x"?

Su una macchina Linux:

#include <stdio.h> 
int main(void) 
{ 
    printf("%#010x\n", 0); 
    printf("%#010x\n", 1); 
    return 0; 
} 

uscita (usando glibc) è:

0000000000 
0x00000001 

uscita sul nostro firmwware era:

0x00000000 
0x00000001 

Da printf (3), sulla il carattere "#" flag: "Per le conversioni x e X, un risultato diverso da zero ha la stringa" 0x "(o" 0X "per X convers ioni) si è preposto ad esso. "

Sono curioso perché. Senza scavare nei documenti standard C o comprare il pranzo per i membri del comitato standard, perché non un 0x iniziale su un argomento a valore zero?

+1

ipotesi selvaggia: 0 è 0 indipendentemente dalla base, quindi non è necessario specificarlo. –

+9

Vale la pena notare che è possibile ottenere il comportamento di * sempre * compreso un '0x' iniziale scrivendo' "0x% 08x" ', mentre il comportamento descritto standard sarebbe più complesso da ottenere da una libreria che * sempre * includeva il che porta a '0x'. Forse la commissione per gli standard stava ottimizzando per un caso più difficile da ottenere, piuttosto che per il caso assolutamente più comune? (Naturalmente, non puoi cambiare '"% # 10x "' a '" 0x% 8x "', ma poi, è difficile immaginare qualcuno che voglia vedere '0x0' senza padding zero.) – ruakh

+2

Non si fa menzione di questo nella [C89 Rationale] (http://www.lysator.liu.se/c/rat/title.html) (HTML) o nella [C99 Rationale] (http: //www.open-std. org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf) (PDF). –

risposta

21

La norma sembra essere scritta in questo modo:

  • %#x e %#o cercare di garantire che l'uscita può essere analizzato correttamente utilizzando strtol con base = 0.

  • In questi casi, la bandiera # aggiunge come pochi caratteri extra come possibile. Ad esempio, 0 viene stampato come 0 perché non è necessario aggiungere il 0x aggiuntivo. Questo ha molto senso se lo si fa non specificare la larghezza minima del campo e 0-padding.

  • Se si desidera aggiungere 0x sempre, spesso è sufficiente scrivere qualcosa come 0x%x. Quindi %#x sembrerebbe essere utile solo in quei casi particolari in cui si ha realmente desidera la gestione speciale di 0. Ma la pre-attesa di 0x non funziona bene con larghezza di campo predefinito prescrittori ad esempio) 0x%12x è giustificato a destra da spazi vuoti tra il 0x e le cifre esadecimali, che è improbabile che sia ciò che è voluto in quel caso. In questo caso sarebbe necessario un ulteriore passaggio preparatorio con sprintf, quindi una stringa esadecimale come "0x2ac2" può essere giustificata correttamente con qualcosa come printf("%12s", hexstr); Fortunatamente giustificare con 0 anziché spazi che utilizzano qualcosa come printf("0x%012x", hexstr); funziona come previsto producendo cifre esadecimali valide per un parser .

Ora il modo in cui lo %#x viene specificato per funzionare ha molto senso da isolare. E il modo in cui qualcosa come %010x è specificato per funzionare ha molto senso da solo. Stai combinando questi due modificatori e il risultato finale è, forse, strano. Per un'altra applicazione, come la generazione automatica di codice C per inizializzare le tabelle, avere 0, anziché 0x0 non è un problema.

Ma non è necessario combinare %#x e %010x.Potresti semplicemente scrivere 0x%08x per fare quello che vuoi.

+1

E dopo aver postato la risposta, ho notato che @ruakh aveva già dato le stesse informazioni in un commento. Scuse. –

+6

+1. Non c'è bisogno di scusarsi. Le risposte sono migliori dei commenti. Ho postato i miei pensieri come un commento, piuttosto che una risposta, perché sapevo che non potevano essere completi; ma la tua risposta è molto più approfondita e ha molto senso. – ruakh

+0

Sia la risposta che i commenti sono apprezzati! L'idea di essere compatibile con strtol ha senso. Ora il tempo per me di andare a cambiare un sacco di codice in 0x% 08x. –