Printf() форматирование для hex
Это более любопытный запрос, чем важный вопрос, но почему при печати шестнадцатеричного числа с 8-значным номером с ведущими нулями этот %#08X
не отображает тот же результат, что и 0x%08X
?
Когда я пытаюсь использовать первое, флаг форматирования 08
удаляется, и он не работает только с 8
.
Снова мне было просто любопытно.
Ответы
Ответ 1
Часть #
дает вам 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
Ответ 2
"0x" подсчитывается к восьмизначному счету. Вам нужно "%#010x"
.
Обратите внимание, что #
не добавляет 0x к 0 - результат будет 0000000000
- так что вы, вероятно, должны просто использовать "0x%08x"
в любом случае.
Ответ 3
Преобразованию %#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
опущен, но с двумя отдельными системами это должно быть стандартным. Это подтверждает мои предубеждения против опции #
.
Обработка нуля в соответствии со стандартом.
Characters6 Знаки флага и их значения:
...
#
Результат конвертируется в "альтернативную форму".... Для преобразования x
(или X
) ненулевой результат имеет префикс 0x
(или 0X
)....
(Акцент добавлен.)
Обратите внимание, что использование %#X
будет использовать заглавные буквы для шестнадцатеричных цифр и 0X
в качестве префикса; использование %#x
будет использовать строчные буквы для шестнадцатеричных цифр и 0x
в качестве префикса. Если вы предпочитаете 0x
в качестве префикса и заглавных букв, вы должны кодировать 0x
отдельно: 0x%X
Конечно, при необходимости можно добавлять другие модификаторы формата.
Для печати адресов используйте заголовок <inttypes.h>
тип uintptr_t
и PRIXPTR
формата 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-битный код).