printf () форматирование для hex

192

Это скорее любопытный запрос, чем важный вопрос, но почему при печати шестнадцатеричного числа в виде 8-значного числа с начальными нулями этот %#08XNot не отображает тот же результат, что и 0x%08X?

Когда я пытаюсь использовать первый, 08флаг форматирования удаляется, и он не работает только с 8.

Снова мне было просто любопытно.

wsmccusker
источник
3
Вы имеете в виду 0x%.8X? Это будет приводить заполняются нулями. ( 0xэто просто преамбула, но вы, вероятно, уже знаете об этом).
WhozCraig

Ответы:

283

#Часть дает вам 0xв выходной строке. Число 0и xчисло против ваших "8" символов, перечисленных в 08части. Вам нужно попросить 10 символов, если вы хотите, чтобы он был таким же.

int i = 7;

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

Также меняется регистр x, влияет на регистр выводимых символов.

printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB
Майк
источник
Верхняя строка выводит 14F0x00000007 для меня. Вторая и третья работа как написано.
Quantumpotato
@quantumpotato - Это ... странно. Первая и третья строки идентичны, за исключением числа 0, которое они должны произвести. Каким был ваш компилятор / система / строка кода, которая произвела это? У вас были какие-нибудь строки, которые печатались 14F?
Майк
19
Обратите внимание, что если i = 0;версии, использующие %#не будет включать 0xпрефикс.
Джонатан Леффлер
но как насчет hex: 0x43A66C31C68491C0 Я пробовал следующее: __int64 int64 = 0x43A66C31C68491C0; printf_s ("% # 15X% d", int64, int64); Но на выходе получается 0XC68491C0, а не 0x43A66C31C68491C0
123iamking
О шестнадцатеричном 0x43A66C31C68491C0 выше, я решил его, решение 0x% I64X, а не% # 15X
123iamking
53

«0x» учитывает счет до восьми символов. Вам нужно "%#010x".

Обратите внимание, что #это не добавляет 0x к 0 - результат будет 0000000000- так что вы, вероятно, на самом деле должны просто использовать в "0x%08x"любом случае.

Random832
источник
34

%#08XПреобразование должно предшествовать значение с 0X; это требуется стандартом. В стандарте нет никаких доказательств того, что они #должны изменять поведение 08части спецификации, за исключением того, что 0Xпрефикс считается частью длины (так что вы можете / должны использовать %#010X. Если, как и я, вам нравится ваш гекс, представленный как 0x1234CDEF, затем вы должны использовать 0x%08Xдля достижения желаемого результата. Вы можете использовать, %#.8Xи это также должно вставить ведущие нули.

Попробуйте варианты в следующем коде:

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

На машине с RHEL 5, а также на Mac OS X (10.7.5) вывод был:

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

Я немного удивлен лечением 0; Я не понимаю, почему 0Xпрефикс пропущен, но с двумя отдельными системами это должно быть стандартным. Это подтверждает мои предубеждения против #варианта.


Обработка нуля в соответствии со стандартом.

ISO / IEC 9899: 2011 §7.21.6.1 функцияfprintf

Characters6 Символы флага и их значения:
...
#Результат преобразуется в «альтернативную форму». ... Для x(или X) преобразования ненулевой результат имеет 0x(или 0X) префикс к нему. ...

(Акцент добавлен.)


Обратите внимание, что при использовании %#Xбудут использоваться заглавные буквы для шестнадцатеричных цифр и 0Xв качестве префикса; Использование %#xбудет использовать строчные буквы для шестнадцатеричных цифр и 0xв качестве префикса. Если вы предпочитаете в 0xкачестве префикса и прописных букв, вы должны коде 0xотдельно: 0x%X. Разумеется, при необходимости можно добавлять другие модификаторы формата.

Для печати адресов используйте <inttypes.h>заголовок, uintptr_tтип и 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;
}

Пример вывода:

Address 0x7FFEE5B29428

Выбери свой яд по длине - я считаю, что точность 12 хорошо работает для адресов на Mac под управлением macOS. В сочетании с .указанием минимальной точности (цифр) он надежно форматирует адреса. Если вы установите точность до 16, дополнительные 4 цифры всегда будут равны 0 в моем опыте на Mac, но, безусловно, есть смысл использовать 16 вместо 12 в переносимом 64-битном коде (но вы бы использовали 8 для 32-битный код).

Джонатан Леффлер
источник