如何将字节打印为十六进制
How do I print bytes as hexadecimal?
我知道在C#中你可以使用String.Format方法。但是,如何在C++做到这一点呢?有没有一个函数可以让我将字节转换为十六进制?只需要将 8 字节长的数据转换为十六进制,我该怎么做?
如果要使用 C++ 流而不是 C 函数,可以执行以下操作:
int ar[] = { 20, 30, 40, 50, 60, 70, 80, 90 };
const int siz_ar = sizeof(ar) / sizeof(int);
for (int i = 0; i < siz_ar; ++i)
cout << ar[i] << " ";
cout << endl;
for (int i = 0; i < siz_ar; ++i)
cout << hex << setfill('0') << setw(2) << ar[i] << " ";
cout << endl;
很简单。
输出:
20 30 40 50 60 70 80 90
14 1e 28 32 3c 46 50 5a
好吧,您可以一次将一个字节(无符号字符)转换为这样的数组
char buffer [17];
buffer[16] = 0;
for(j = 0; j < 8; j++)
sprintf(&buffer[2*j], "%02X", data[j]);
C:
static void print_buf(const char *title, const unsigned char *buf, size_t buf_len)
{
size_t i = 0;
fprintf(stdout, "%sn", title);
for(i = 0; i < buf_len; ++i)
fprintf(stdout, "%02X%s", buf[i],
( i + 1 ) % 16 == 0 ? "rn" : " " );
}
C++:
void print_bytes(std::ostream& out, const char *title, const unsigned char *data, size_t dataLen, bool format = true) {
out << title << std::endl;
out << std::setfill('0');
for(size_t i = 0; i < dataLen; ++i) {
out << std::hex << std::setw(2) << (int)data[i];
if (format) {
out << (((i + 1) % 16 == 0) ? "n" : " ");
}
}
out << std::endl;
}
C++20 std::format
来执行此操作,这与 C# 中的 String.Format
类似:
std::string s = std::format("{:x}", std::byte(42)); // s == 2a
在std::format
广泛可用之前,您可以使用 {fmt} 库,std::format
基于 (godbolt):
std::string s = fmt::format("{:x}", std::byte(42)); // s == 2a
免责声明:我是{fmt}和C++20 std::format
的作者。
在现代C++中打印任意结构
到目前为止,所有答案都只告诉您如何打印整数数组,但鉴于我们知道它的大小,我们也可以打印任何任意结构。下面的示例创建这样的结构,并通过其字节迭代指针,将它们打印到输出中:
#include <iostream>
#include <iomanip>
#include <cstring>
using std::cout;
using std::endl;
using std::hex;
using std::setfill;
using std::setw;
using u64 = unsigned long long;
using u16 = unsigned short;
using f64 = double;
struct Header {
u16 version;
u16 msgSize;
};
struct Example {
Header header;
u64 someId;
u64 anotherId;
bool isFoo;
bool isBar;
f64 floatingPointValue;
};
int main () {
Example example;
// fill with zeros so padding regions don't contain garbage
memset(&example, 0, sizeof(Example));
example.header.version = 5;
example.header.msgSize = sizeof(Example) - sizeof(Header);
example.someId = 0x1234;
example.anotherId = 0x5678;
example.isFoo = true;
example.isBar = true;
example.floatingPointValue = 1.1;
cout << hex << setfill('0'); // needs to be set only once
auto *ptr = reinterpret_cast<unsigned char *>(&example);
for (int i = 0; i < sizeof(Example); i++, ptr++) {
if (i % sizeof(u64) == 0) {
cout << endl;
}
cout << setw(2) << static_cast<unsigned>(*ptr) << " ";
}
return 0;
}
这是输出:
05 00 24 00 00 00 00 00
34 12 00 00 00 00 00 00
78 56 00 00 00 00 00 00
01 01 00 00 00 00 00 00
9a 99 99 99 99 99 f1 3f
请注意,此示例还说明了内存对齐的工作原理。我们看到version
占用 2 个字节 ( 05 00
),然后是 msgSize
另外 2 个字节 ( 24 00
),然后是 4 个字节的填充,然后是 someId
( 34 12 00 00 00 00 00 00
) 和 anotherId
( 78 56 00 00 00 00 00 00
)。然后isFoo
,它占用1个字节(01
),isBar
,另一个字节(01
),然后是6个字节的填充,最后以IEEE 754标准表示的双字段floatingPointValue
结束。
另请注意,所有值都表示为小端序(最低有效字节在前),因为它是在英特尔平台上编译和运行的。
这是 Nibble to Hex 方法的修改版本
void hexArrayToStr(unsigned char* info, unsigned int infoLength, char **buffer) {
const char* pszNibbleToHex = {"0123456789ABCDEF"};
int nNibble, i;
if (infoLength > 0) {
if (info != NULL) {
*buffer = (char *) malloc((infoLength * 2) + 1);
buffer[0][(infoLength * 2)] = 0;
for (i = 0; i < infoLength; i++) {
nNibble = info[i] >> 4;
buffer[0][2 * i] = pszNibbleToHex[nNibble];
nNibble = info[i] & 0x0F;
buffer[0][2 * i + 1] = pszNibbleToHex[nNibble];
}
} else {
*buffer = NULL;
}
} else {
*buffer = NULL;
}
}
更好的方法:
unsigned char byData[xxx];
int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
sprintf(pBuffer[2 * i], "%02X", byData[i]);
}
您可以使用半字节到十六进制方法加快速度
unsigned char byData[xxx];
const char szNibbleToHex = { "0123456789ABCDEF" };
int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
// divide by 16
int nNibble = byData[i] >> 4;
pBuffer[2 * i] = pszNibbleToHex[nNibble];
nNibble = byData[i] & 0x0F;
pBuffer[2 * i + 1] = pszNibbleToHex[nNibble];
}
另一个答案,如果字节数组被定义为 char[]
,大写并用空格分隔。
void debugArray(const unsigned char* data, size_t len) {
std::ios_base::fmtflags f( std::cout.flags() );
for (size_t i = 0; i < len; ++i)
std::cout << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (((int)data[i]) & 0xFF) << " ";
std::cout << std::endl;
std::cout.flags( f );
}
例:
unsigned char test[]={0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
debugArray(test, sizeof(test));
输出:
01 02 03 04 05 06
使用C++流并在之后恢复状态
这是如何将字节打印为十六进制的变体? 但是:
- 可运行
- 考虑到这会改变 cout 的状态,并尝试在最后恢复它,如以下位置要求:在操作 std::cout 后恢复它的状态
主.cpp
#include <iomanip>
#include <iostream>
int main() {
int array[] = {0, 0x8, 0x10, 0x18};
constexpr size_t size = sizeof(array) / sizeof(array[0]);
// Sanity check decimal print.
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
// Hex print and restore default afterwards.
std::ios cout_state(nullptr);
cout_state.copyfmt(std::cout);
std::cout << std::hex << std::setfill('0') << std::setw(2);
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
std::cout.copyfmt(cout_state);
// Check that cout state was restored.
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << " ";
std::cout << std::endl;
}
编译并运行:
g++ -o main.out -std=c++11 main.cpp
./main.out
输出:
0 8 16 24
00 8 10 18
0 8 16 24
在 Ubuntu 16.04、GCC 6.4.0 上测试。
另一个 C++17 替代方案,因为为什么不呢!
std::cout<<std::hex<<std::setfill('0');
struct {
std::uint16_t first{666};
std::array<char,4> second{'a','b','c','d'};
} my_struct;
auto ptr = reinterpret_cast<std::byte*>(&my_struct);
auto buffer = std::vector<std::byte>(ptr, ptr + sizeof(my_struct));
std::for_each(std::begin(buffer),std::end(buffer),[](auto byte){
std::cout<<std::setw(2)<<std::to_integer<int>(byte)<<' ';
});
可执行代码在这里。
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- C ++如何使用UTF8十六进制代码打印UTF8符号?
- 打印十六进制字符
- 编译器始终打印十六进制/八进制数字
- 在 c++ 中以十六进制格式打印无符号字符(BYTE).使用 std::cout
- 以十六进制打印出 DWORD 会在 win32 c++ 中返回0x7FFFFFFF
- 将长整型值打印为带有前导零的十六进制
- C++ 在地板函数之后以十六进制打印数字
- 如何使系统在十六进制数之前打印 0x,在八进制数之前打印 0?
- 打印出浮点数的内部十六进制
- 为什么 std::hex 没有特别用字符打印为十六进制?
- 我如何在GDB中打印十六进制的双重位
- C/C++ 以十六进制打印字节,得到奇怪的十六进制值
- 尝试将二进制数组转换为十六进制C++然后打印结果
- 如何从uint32_t打印十六进制
- 用IO操纵器在十六进制中打印一个8位号码
- 将内存地址中的值打印为十六进制C++
- fprintf:打印文字十六进制字符串
- 将十六进制转换为可打印的字符串/字符
- 以十六进制打印数据结构值