formatage printf () pour hexadécimal

192

C'est plus une question curieuse qu'une question importante, mais pourquoi lors de l'impression hexadécimale comme un nombre à 8 chiffres avec des zéros non significatifs, cela %#08Xn'affiche- t-il pas le même résultat que 0x%08X?

Lorsque j'essaie d'utiliser l'ancien, l' 08indicateur de mise en forme est supprimé et cela ne fonctionne pas avec 8.

Encore une fois, j'étais simplement curieux.

wsmccusker
la source
3
Voulez-vous dire 0x%.8X? Cela va conduire avec des zéros de remplissage. (ce 0xn'est qu'un préambule, mais vous en êtes probablement déjà conscient).
WhozCraig

Réponses:

283

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

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 la casse des caractères sortis.

printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB
Mike
la source
La ligne du haut produit pour moi 14F0x00000007. Le deuxième et le troisième travail tel qu'écrit.
quantumpotato
@quantumpotato - C'est ... bizarre. Les première et troisième lignes sont identiques à l'exception du nombre de 0 qu'elles devraient produire. Quel a été votre compilateur / système / ligne de code qui a produit cela? Aviez-vous des lignes suivant celle imprimée 14F?
Mike
19
Notez que si i = 0;, les versions utilisant %#n'incluront pas le 0xpréfixe.
Jonathan Leffler
mais que diriez-vous de l'hex: 0x43A66C31C68491C0 J'ai essayé ce qui suit: __int64 int64 = 0x43A66C31C68491C0; printf_s ("% # 15X% d", int64, int64); Mais la sortie est 0XC68491C0, pas 0x43A66C31C68491C0
123iamking
À propos de l'hex 0x43A66C31C68491C0 ci-dessus, je l'ai résolu, la solution est 0x% I64X, pas% # 15X
123iamking
53

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

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

Aléatoire832
la source
34

La %#08Xconversion doit précéder la valeur avec 0X; qui est exigé par la norme. Il n'y a aucune preuve dans la norme que le #devrait modifier le comportement de la 08partie de la spécification sauf que le 0Xpréfixe est compté comme faisant partie de la longueur (vous pourriez donc vouloir / avoir besoin de l'utiliser %#010X. Si, comme moi, vous aimez votre hexa présenté comme 0x1234CDEF, alors vous devez utiliser 0x%08Xpour obtenir le résultat souhaité. Vous pouvez utiliser %#.8Xet cela devrait également insérer les zéros non significatifs.

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 du traitement de 0; Je ne sais pas pourquoi le 0Xpréfixe 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 fprintffonction

¶6 Les caractères du drapeau et leur signification sont:
...
#Le résultat est converti en une "forme alternative". ... Pour x(ou X) la conversion, un résultat différent de zéro a 0x(ou 0X) préfixé. ...

(Je souligne.)


Notez que l'utilisation %#Xutilisera des lettres majuscules pour les chiffres hexadécimaux et 0Xcomme préfixe; using %#xutilisera des lettres minuscules pour les chiffres hexadécimaux et 0xcomme préfixe. Si vous préférez 0xque le préfixe et les lettres majuscules, vous devez coder la 0xséparément: 0x%X. D'autres modificateurs de format peuvent être ajoutés au besoin, bien sûr.

Pour imprimer des adresses, utilisez l'en- <inttypes.h>tête et le uintptr_ttype et la PRIXPTRmacro de format:

#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 fonctionne bien pour les adresses sur un Mac exécutant macOS. Combiné avec le .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 0 selon mon expérience sur le Mac, mais il y a certainement un cas à utiliser pour utiliser 16 au lieu de 12 dans un code 64 bits portable (mais vous utiliseriez 8 pour Code 32 bits).

Jonathan Leffler
la source