Странное поведение в boost::format hex

Я пытаюсь отформатировать двоичный массив: char* memblock в шестнадцатеричную строку.

Когда я использую следующее:

fprintf(out, "0x%02x,", memblock[0]);

Я получаю следующий вывод:

0x7f,

Когда я пытаюсь использовать boost::format на офстриме вот так:

std::ofstream outFile (path, std::ios::out); //also tried with binary
outFile << (boost::format("0x%02x")%memblock[0]);

Я получаю странный вывод, как это (видно в Vi): 0x0^?,

Что дает?

1 ответ

Решение

Учитывая, что персонаж для 0x7f такое CTRL-? похоже, это выводит memblock[0] как символ, а не как шестнадцатеричное значение, несмотря на вашу строку формата.

Это на самом деле имеет смысл, основываясь на том, что я прочитал в документации. Boost::format является типобезопасной библиотекой, где спецификаторы формата определяют, как будет выводиться переменная, но ограничены фактическим типом указанной переменной, которая имеет приоритет.

В документации говорится (мой жирный):

Устаревшие строки формата printf: %spec где spec это printf спецификация формата.

spec передает параметры форматирования, такие как ширина, выравнивание, числовая база, используемая для форматирования чисел, а также другие конкретные флаги. Но классический флаг спецификации типа printf имеет более слабое значение в формате.

Он просто устанавливает соответствующие флаги во внутреннем потоке и / или параметрах форматирования, но не требует, чтобы соответствующий аргумент был определенного типа. например: спецификация 2$xЗначение "print аргумент № 2, который является целым числом в гекса" для printf, просто означает "аргумент печати 2 с установленными в шестнадцатеричном формате флагами потокового поля" для формата.

И, по-видимому, установка флажка в поле hex не имеет большого смысла, когда вы печатаете charтак что игнорируется. Дополнительно из этой документации (хотя перефразируя немного):

type-char не навязывает рассматриваемый аргумент ограниченному набору типов, а просто устанавливает флаги, связанные с этой спецификацией типа. type-char из p или же x означает шестнадцатеричный вывод, но просто устанавливает шестнадцатеричный флаг в потоке.

Это также более конкретно подтверждается текстом по этой ссылке:

Мои коллеги и я обнаружили, однако, что когда %d дескриптор используется для печати char Переменная результат как будто %c дескриптор был использован - printf а также boost::format не дают тот же результат.

В документации Boost, связанной с выше, также объясняется, что заполнение нулями 0 Модификатор работает на всех типах, а не только на целых, поэтому вы получаете второй 0 в 0x0^? (^? это один символ).


Во многом это похоже на проблему попытки вывести const char * в C++, так что вы видите указатель. Следующий код:

#include <iostream>
int main() {
   const char *xyzzy = "plugh";
   std::cout << xyzzy << '\n';
   std::cout << (void*)xyzzy << '\n';
   return 0;
}

будет производить что-то вроде:

plugh
0x4009a0

потому что стандартные библиотеки знают, что строки в стиле C являются особым случаем, но, если вы скажете им, что это указатель void, они выдадут вам указатель в качестве вывода.

Решение в вашем конкретном случае может быть просто char для int или какой-то другой тип, который интеллектуально обрабатывает %x спецификатор формата:

outFile << (boost::format("0x%02x") % static_cast<int>(memblock[0]));
Другие вопросы по тегам