print long hexadecimal float c hex printf

long - ¿Por qué se imprime 0(cero) sin encabezar "0x" con formato de impresión C "%#x"?



printf string c (1)

Antecedentes: Tengo varios scripts que analizan los archivos de registro en busca de números hexadecimales al encontrar el "0x" al principio. Nuestra biblioteca C incrustada cambió a un nuevo printf. El nuevo printf es más compatible con los estándares que nuestro anterior y mis scripts se rompieron.

En una caja de Linux:

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

La salida (usando glibc) es:

0000000000 0x00000001

La salida en nuestro firmware fue:

0x00000000 0x00000001

Desde printf (3), en el carácter de marca ''#'': "Para las conversiones de x y X, un resultado distinto de cero tiene la cadena" 0x "(o" 0X "para las conversiones de X) precedida".

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


El estándar parece estar escrito de esta manera:

  • %#x y %#o intenta garantizar que la salida se pueda analizar correctamente usando strtol con base = 0 .

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

  • Si siempre quisieras agregar 0x , a menudo simplemente podrías escribir algo como 0x%x . Por lo tanto, %#x parece ser útil solo en aquellos casos especiales en los que realmente desea un manejo especial de 0. Pero la pendiente pendiente de 0x no funciona bien con los especificadores de ancho de campo predeterminados, por ejemplo, 0x%12x está justificado a la derecha por espacios en blanco entre los dígitos 0x y hexadecimales, lo que probablemente no sea lo que se desea en ese caso Para este caso, se requeriría un pase preparatorio adicional con sprintf, por lo que una cadena hexagonal como "0x2ac2" puede ser un espacio en blanco justificado a la derecha con algo como printf( "%12s", hexstr); Afortunadamente, justifica con 0 lugar de espacios utilizando algo como printf( "0x%012x", hexstr); Funciona como se espera produciendo dígitos hexadecimales válidos para un analizador.

Ahora la forma en que %#x se especifica para trabajar tiene mucho sentido de forma aislada. Y la forma en que algo como %010x se especifica para funcionar tiene mucho sentido de forma aislada. Está 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 puro para inicializar tablas, tener 0, lugar de 0x0 no es un problema.

Pero no es necesario combinar %#x y %010x . Podrías escribir 0x%08x para hacer lo que quieras.