форматування printf () для шістнадцяткової


191

Це скоріше цікавий запит, ніж важливе питання, але чому при друку шістнадцяткових знаків у вигляді 8-значного числа з провідними нулями це %#08Xне відображає такого ж результату, як 0x%08X?

Коли я намагаюся використовувати колишній, 08прапор форматування видаляється, і він не працює просто 8.

Знову мені було просто цікаво.


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 - Це ... дивно. Перший і третій рядки ідентичні за винятком кількості 0, яку вони повинні створити. Який ваш компілятор / система / рядок коду, що це призвів? Чи були у вас будь-які рядки, що переглядали той, який надрукували 14F?
Майк

19
Зауважте, що якщо i = 0;, використовувані версії %#не включатимуть 0xпрефікс.
Джонатан Леффлер

а як щодо шестигранної: 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"будь-якому випадку.


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

¶6 Символи прапора та їх значення такі:
...
#Результат перетворюється на "альтернативну форму". ... Для 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-бітний код).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.