printf()-opmaak voor hexadecimaal

Waarom geeft %#08Xniethetzelfde resultaat weer als 0x%08X?

Als ik de eerste probeer te gebruiken, wordt de opmaakvlag 08verwijderd en werkt het niet alleen met 8.


Antwoord 1, autoriteit 100%

Het #gedeelte geeft je een 0xin de output string. De 0en de xtellen mee voor uw “8”-tekens in het 08-gedeelte. Je moet om 10 tekens vragen als je wilt dat het hetzelfde is.

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

Ook het wijzigen van de hoofdletters van xheeft invloed op de hoofdletters van de uitgevoerde tekens.

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

Antwoord 2, autoriteit 19%

De “0x” telt mee voor het aantal tekens van acht tekens. Je hebt "%#010x"nodig.

Merk op dat #nietde 0x aan 0 toevoegt – het resultaat zal 0000000000zijn – dus u moet waarschijnlijk gewoon "0x%08x"toch.


Antwoord 3, autoriteit 12%

De %#08Xconversie moet voorafgaan aan de waarde met 0x; dat vereist de norm. Er is geen bewijs in de standaard dat het #het gedrag van het 08deel van de specificatie zou moeten veranderen, behalve dat het 0xvoorvoegsel als onderdeel wordt geteld van de lengte (dus misschien wil/moet je %#010Xgebruiken. Als je, net als ik, je hex wilt presenteren als 0x1234CDEF, dan moet je 0x%08Xom het gewenste resultaat te bereiken. Je zou %#.8Xkunnen gebruiken en dat zou ook de voorloopnullen moeten invoegen.

Probeer variaties op de volgende code:

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

Op een RHEL5-machine, en ook op Mac OS X v10.7.5(Lion), de output was:

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

Ik ben een beetje verbaasd over de behandeling van 0; Ik ben niet duidelijk waarom de 0xvoorvoegsel wordt weggelaten, maar met twee gescheiden systemen te doen, het moet standaard zijn. Het bevestigt mijn vooroordelen tegen de #optie.


De behandeling van nul komt overeen met de standaard.

ISO / IEC 9899: 2011 §7.21.6.1 De fprintf

¶6 De vlag personages en hun betekenis zijn:

#Het resultaat wordt omgezet in een “variant”. Voor … x(of x)
conversie, een niet-nul resultaat moet 0x(of 0x) vooraf aan. …

(nadruk toegevoegd).


Merk op dat met %#Xgebruiken hoofdletters voor hexadecimale cijfers en 0xals voorvoegsel; met %#Xgebruiken kleine letters voor hexadecimale cijfers en 0xals voorvoegsel. Als u liever 0xals voorvoegsel en hoofdletters, moet u de code van de 0xafzonderlijk: 0x%X. Andere formaat modifiers kunnen worden toegevoegd als nodig is, natuurlijk.

Voor het afdrukken van adressen, gebruikt u de <inttypes.h>header en de uintptr_ttype en de PRIXPTRformaat macro:

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

Resultaat:

Address 0x7FFEE5B29428

Kies je gif op de lengte — ik vind dat een precisie van 12 goed werkt voor adressen op een Mac met macOS. Gecombineerd met de .om de minimale precisie (cijfers) te specificeren, maakt het adressen betrouwbaar op. Als je de precisie instelt op 16, zijn de extra 4 cijfers altijd 0 in mijn ervaring op de Mac, maar er is zeker een argument om 16 te gebruiken in plaats van 12 in draagbare 64-bits code (maar je zou 8 gebruiken voor 32-bits code).


Antwoord 4, autoriteit 2%

#zorgt ervoor dat 0x(of 0xvoor %#X) aan de uitvoer wordt toegevoegd, tenzij de waarde is 0, dus u moet #niet gebruiken als u wilt dat 0xaltijd in de uitvoer verschijnt.

U kunt het breedteveld in combinatie met de vlag 0gebruiken om voorloopnullen te produceren: %08xvult het getal met voorloopnullen in tot een breedte van 8. Als u consistente uitvoer wilt voor alle 32-bits waarden, gebruikt u "0x08x".

U kunt ook het precisieveld gebruiken: %.8xvult het getal in met voorloopnullen tot een totaal van 8cijfers. Daarom kunt u ook "0x%.8x"gebruiken voor uw doel.

Deze conversiespecificaties zouden verschillen als er een prefix wordt gegenereerd als onderdeel van de conversie, zoals 0xvoor #of -voor negatieve getallen in ondertekende conversies, waarvan de lengte wordt meegeteld voor de breedte, maar niet voor de precisiespecificatie. Verder kan het precisieveld worden gecombineerd met het breedteveld:

printf("|%10x|", 256)      // outputs |       100|
printf("|%010x|", 256)     // outputs |0000000100|
printf("|%#010x|", 256)    // outputs |0x00000100|
printf("|%10.8x|", 256)    // outputs |  00000100|
printf("|%#10.8x|", 256)   // outputs |0x00000100|
printf("|0x%.8x|", 256)    // outputs |0x00000100|
printf("|%10x|", 0)        // outputs |         0|
printf("|%010x|", 0)       // outputs |0000000000|
printf("|%#010x|", 0)      // outputs |0000000000|
printf("|%10.8x|", 0)      // outputs |  00000000|
printf("|%#10.8x|", 0)     // outputs |  00000000|
printf("|0x%.8x|", 0)      // outputs |0x00000000|

Ik zou aanraden de laatste te gebruiken: "0x%.8x".


Antwoord 5

U kunt altijd “%p” gebruiken om 8-bits hexadecimale getallen weer te geven.

int main (void)
{
    uint8_t a;
    uint32_t b;
    a = 15;
    b = a << 28;
    printf("%p", b);
    return 0;
}

Uitvoer:

0xf0000000

Other episodes