2011-12-14 21 views
27

Antecedentes: tengo una serie de scripts que analizan los archivos de registro en busca de números hexadecimales al encontrar el "0x" inicial. Nuestra biblioteca C incrustada cambió a una nueva printf. El nuevo printf es más compatible con los estándares que nuestro anterior y mis scripts se rompieron.¿Por qué se imprime 0 (cero) sin "0x" al comienzo con el formato C printf "% # x"?

en una máquina Linux:

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

salida (usando glibc) es:

0000000000 
0x00000001 

de salida en nuestro firmwware era:

0x00000000 
0x00000001 

De printf (3), en el carácter de la bandera '#': "Para x y X conversiones, un resultado distinto de cero tiene la cadena" 0x "(o" 0X "para X convers iones) precede a ella ".

Tengo curiosidad por qué. Sin excavar los documentos de estándares de C o comprar el almuerzo para los miembros del comité de normas, ¿por qué no un 0x líder en un argumento de valor cero?

+1

Wild guess: 0 es 0 independientemente de la base, por lo que no hay necesidad de especificarlo. –

+9

Vale la pena señalar que puede obtener el comportamiento de * siempre * incluyendo un '0x' inicial al escribir '" 0x% 08x "', mientras que el comportamiento descrito de manera estándar sería más complicado de obtener de una biblioteca que * siempre * incluía el liderando '0x'. Tal vez el comité de estándares estaba optimizando para un caso más difícil de conseguir, en lugar del caso absolutamente más común. (Por supuesto, no puede cambiar '"% # 10x "' a '" 0x% 8x "', pero entonces, es difícil imaginar que alguien quiera ver '0x0' sin relleno cero). – ruakh

+2

No hay mención de esto en [C89 Rationale] (http://www.lysator.liu.se/c/rat/title.html) (HTML) o en [C99 Rationale] (http: //www.open-std. org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf) (PDF). –

Respuesta

21

La norma parece estar escrita de esta manera:

  • %#x y %#o tratan de garantizar que la salida se puede analizar correctamente utilizando strtol con base = 0.

  • En estos casos, la bandera # agrega como pocos caracteres adicionales como posible. Por ejemplo, 0 se imprime como 0 porque no es necesario agregar el 0x adicional. Esto tiene mucho sentido si lo haces no especifica el ancho de campo mínimo y 0-relleno.

  • Si desea agregar 0x siempre, a menudo puede simplemente escribir algo como 0x%x. Por lo tanto %#x parece ser útil solamente en aquellos casos especiales en los que usted realmente desea el manejo especial de 0. Sin embargo, el pre-pendiente de 0x no funciona bien con especificadores de ancho de campo predeterminado, por ejemplo) 0x%12x es justificado a la derecha por espacios en blanco entre los dígitos 0x y hex, que es poco probable que sea lo que se quiere en ese caso. Para este caso se requeriría un pase de preparación adicional con sprintf, por lo que una cadena hexadecimal como "0x2ac2" puede ser un espacio en blanco justificado a la derecha con algo como printf("%12s", hexstr); Afortunadamente justificando con 0 en lugar de espacios usando algo como printf("0x%012x", hexstr); funciona como se espera producir dígitos hexadecimales válidos para un analizador .

Ahora, la forma %#x se especifica que el trabajo tiene mucho sentido en el aislamiento. Y la forma en que se especifica algo como %010x para trabajar tiene mucho sentido de forma aislada. Estás combinando estos dos modificadores, y el resultado final es, posiblemente, extraño. Para otra aplicación, como la generación automática de código C limpio para inicializar tablas, tener 0, en lugar de 0x0 no es un problema.

Pero no es necesario combinar %#x y %010x.Simplemente puede escribir 0x%08x para hacer lo que quiera.

+1

Y después de publicar la respuesta, noté que @ruakh ya había dado esencialmente la misma información en un comentario. Disculpas –

+6

+1. No hay necesidad de disculparse. Las respuestas son mejores que los comentarios. Publiqué mis pensamientos como un comentario, en lugar de una respuesta, porque sabía que no podían ser completos; pero tu respuesta es mucho más completa y tiene mucho sentido. – ruakh

+0

¡Tanto la respuesta como los comentarios son apreciados! La idea de ser compatible con strtol tiene sentido. Ahora es hora de que cambie un montón de código a 0x% 08x. –

Cuestiones relacionadas