formato printf () para hexadecimal

192

Esto es más una consulta curiosa que una pregunta importante, pero ¿por qué cuando se imprime hexadecimal como un número de 8 dígitos con ceros a la izquierda, esto %#08Xno muestra el mismo resultado que 0x%08X?

Cuando trato de usar el primero, 08se elimina el indicador de formato y no funciona solo 8.

De nuevo solo tenía curiosidad.

wsmccusker
fuente
3
Qué quiere decir 0x%.8X? Eso se llenará con ceros. (el 0xes solo un preámbulo, pero es probable que ya lo sepas).
WhozCraig

Respuestas:

283

La #parte le da un 0xen la cadena de salida. El 0y el xrecuento en contra de sus "8" personajes enumerados en la 08parte. Necesitas pedir 10 caracteres si quieres que sea el mismo.

int i = 7;

printf("%#010x\n", i);  // gives 0x00000007
printf("0x%08x\n", i);  // gives 0x00000007
printf("%#08x\n", i);   // gives 0x000007

También cambiar el caso de x, afecta a la carcasa de los caracteres de salida.

printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB
Miguel
fuente
La línea superior emite 14F0x00000007 para mí. El segundo y tercer trabajo tal como están escritos.
quantumpotato
@quantumpotato - Eso es ... extraño. La primera y la tercera línea son idénticas con la excepción del número de 0 que deberían producir. ¿Cuál fue su compilador / sistema / línea de código que produjo esto? ¿Tuviste alguna línea detrás de la que se imprimió 14F?
Mike
19
Tenga en cuenta que si i = 0;las versiones que usan %#no incluirán el 0xprefijo.
Jonathan Leffler
pero qué tal el hexadecimal: 0x43A66C31C68491C0 He intentado lo siguiente: __int64 int64 = 0x43A66C31C68491C0; printf_s ("% # 15X% d", int64, int64); Pero la salida es 0XC68491C0, no 0x43A66C31C68491C0
123iamking
Sobre el hexadecimal 0x43A66C31C68491C0 anterior, lo tengo resuelto, la solución es 0x% I64X, no% # 15X
123iamking
53

El "0x" cuenta para el recuento de ocho caracteres. Es necesario "%#010x".

Tenga en cuenta que #no no anexar el 0x a 0 - el resultado será 0000000000- por lo que es probable que en realidad sólo debe utilizar "0x%08x"de todos modos.

Aleatorio832
fuente
34

La %#08Xconversión debe preceder al valor con 0X; eso es requerido por el estándar. No hay evidencia en el estándar de que #deba alterar el comportamiento de la 08parte de la especificación, excepto que el 0Xprefijo se cuenta como parte de la longitud (por lo que es posible que desee / necesite usarlo %#010X. Si, como yo, le gusta su hexadecimal presentado como 0x1234CDEF, entonces debe usar 0x%08Xpara lograr el resultado deseado. Puede usar %#.8Xy eso también debe insertar los ceros iniciales.

Pruebe variaciones en el siguiente código:

#include <stdio.h>

int main(void)
{
    int j = 0;
    printf("0x%.8X = %#08X = %#.8X = %#010x\n", j, j, j, j);
    for (int i = 0; i < 8; i++)
    {
        j = (j << 4) | (i + 6);
        printf("0x%.8X = %#08X = %#.8X = %#010x\n", j, j, j, j);
    }
    return(0);
}

En una máquina RHEL 5, y también en Mac OS X (10.7.5), el resultado fue:

0x00000000 = 00000000 = 00000000 = 0000000000
0x00000006 = 0X000006 = 0X00000006 = 0x00000006
0x00000067 = 0X000067 = 0X00000067 = 0x00000067
0x00000678 = 0X000678 = 0X00000678 = 0x00000678
0x00006789 = 0X006789 = 0X00006789 = 0x00006789
0x0006789A = 0X06789A = 0X0006789A = 0x0006789a
0x006789AB = 0X6789AB = 0X006789AB = 0x006789ab
0x06789ABC = 0X6789ABC = 0X06789ABC = 0x06789abc
0x6789ABCD = 0X6789ABCD = 0X6789ABCD = 0x6789abcd

Estoy un poco sorprendido por el tratamiento de 0; No estoy claro por qué 0Xse omite el prefijo, pero con dos sistemas separados que lo hacen, debe ser estándar. Confirma mis prejuicios contra la #opción.


El tratamiento de cero es de acuerdo con el estándar.

ISO / IEC 9899: 2011 §7.21.6.1 La fprintffunción

¶6 Los caracteres de la bandera y sus significados son:
...
#El resultado se convierte a una "forma alternativa". ... Para x(o X) conversión, un resultado distinto de cero tiene 0x(o 0X) prefijado. ...

(Énfasis añadido.)


Tenga en cuenta que usar %#Xusará letras mayúsculas para los dígitos hexadecimales y 0Xcomo prefijo; usar %#xusará letras minúsculas para los dígitos hexadecimales y 0xcomo prefijo. Si prefiere 0xcomo las letras del prefijo y mayúsculas, que tiene que el código 0xpor separado: 0x%X. Se pueden agregar otros modificadores de formato según sea necesario, por supuesto.

Para imprimir direcciones, use el <inttypes.h>encabezado y el uintptr_ttipo y la PRIXPTRmacro de formato:

#include <inttypes.h>
#include <stdio.h>

int main(void)
{
    void *address = &address;  // &address has type void ** but it converts to void *
    printf("Address 0x%.12" PRIXPTR "\n", (uintptr_t)address);
    return 0;
}

Salida de ejemplo:

Address 0x7FFEE5B29428

Elija su veneno en la longitud: encuentro que una precisión de 12 funciona bien para direcciones en una Mac con macOS. Combinado con .para especificar la precisión mínima (dígitos), formatea direcciones de manera confiable. Si establece la precisión en 16, los 4 dígitos adicionales son siempre 0 en mi experiencia en la Mac, pero ciertamente hay un caso para usar 16 en lugar de 12 en código portátil de 64 bits (pero usaría 8 para Código de 32 bits).

Jonathan Leffler
fuente