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 usandostrtol
conbase = 0
.En estos casos, la bandera
#
agrega la menor cantidad de caracteres adicionales posible. Por ejemplo, 0 se imprime como0
porque no es necesario agregar el0x
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 como0x%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 de0x
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 comoprintf( "%12s", hexstr);
Afortunadamente, justifica con0
lugar de espacios utilizando algo comoprintf( "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.