web-dev-qa-db-fra.com

printf () formatant pour hex

Ceci est plus une requête curieuse qu'une question importante, mais pourquoi lors de l'impression hexadécimale avec un nombre à 8 chiffres avec des zéros non significatifs, est-ce que %#08X ne présente pas le même résultat que 0x%08X?

Lorsque j'essaie d'utiliser l'ancien, l'indicateur de formatage 08 est supprimé et il ne fonctionne pas uniquement avec 8.

Encore une fois j'étais simplement curieux.

154
wsmccusker

La partie # vous donne un 0x dans la chaîne de sortie. Le 0 et le x comptent dans vos "8" caractères énumérés dans la partie 08. Vous devez demander 10 caractères si vous voulez que ce soit la même chose.

int i = 7;

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

Changer également la casse de x affecte le casse des caractères sortis.

printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB
247
Mike

Le "0x" compte pour le compte de huit caractères. Vous avez besoin de "%#010x".

Notez que # ne pas ajoute le 0x à 0 - le résultat sera 0000000000 - alors vous devriez probablement utiliser "0x%08x" de toute façon.

51
Random832

La conversion %#08X doit précéder la valeur avec 0X; cela est requis par la norme. Rien dans la norme n'indique que le # doive modifier le comportement de la partie 08 de la spécification, si ce n'est que le préfixe 0X est compté comme faisant partie de la longueur (vous pourriez donc vouloir/devez utiliser %#010X. Si, comme moi, vous aimez votre hexagone présenté sous la forme 0x1234CDEF, vous devez utiliser 0x%08X pour obtenir le résultat souhaité. Vous pouvez aussi utiliser %#.8X. et cela devrait également insérer les zéros au début.

Essayez des variantes du code suivant:

#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);
}

Sur une machine RHEL 5, ainsi que sur Mac OS X (10.7.5), le résultat était:

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

Je suis un peu surpris par le traitement de 0; Je ne comprends pas pourquoi le préfixe 0X est omis, mais avec deux systèmes distincts, il doit être standard. Cela confirme mes préjugés contre l'option #.


Le traitement de zéro est conforme à la norme.

ISO/CEI 9899: 2011 §7.21.6.1 La fonction fprintf

¶6 Les drapeaux et leur signification sont les suivants:
...
# Le résultat est converti en une "forme alternative". ... Pour la conversion x (ou X), a non nulle résultat a le préfixe 0x (ou 0X). ...

(Soulignement ajouté.)


Notez que l'utilisation de %#X utilisera des lettres majuscules pour les chiffres hexadécimaux et 0X comme préfixe; utiliser %#x utilisera des lettres minuscules pour les chiffres hexadécimaux et 0x comme préfixe. Si vous préférez 0x comme préfixe et lettres majuscules, vous devez coder le 0x séparément: 0x%X. Bien entendu, d'autres modificateurs de format peuvent être ajoutés.

Pour imprimer les adresses, utilisez l'en-tête <inttypes.h>, le type uintptr_t et la macro de formatage PRIXPTR:

#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;
}

Exemple de sortie:

Address 0x7FFEE5B29428

Choisissez votre poison sur la longueur - Je trouve qu’une précision de 12 convient bien aux adresses des Mac fonctionnant sous MacOS. Associé au . pour spécifier la précision minimale (chiffres), il formate les adresses de manière fiable. Si vous définissez la précision sur 16, les 4 chiffres supplémentaires sont toujours égaux à 0 dans mon expérience sur Mac, mais il est certainement judicieux d'utiliser 16 dans le code portable 64 bits au lieu de 12 (mais vous utiliseriez 8 pour Code 32 bits).

27
Jonathan Leffler