Странное поведение в 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]));