给定您想要转储字节的任何结构,一种方法是在C ++中实现它,如下所示:
void print_bytes(myst *my_struct)
{
char *ptr = (char *)my_struct;
cout << std::hex;
for (size_t i = 0; i < sizeof(*my_struct); i++) {
cout << ptr + i << ": " << ptr[i];
// similar to printf("%p: 0x%x", ptr + i, ptr[i]) right?
}
}
但上面会打印地址和值的垃圾。为什么呢?
答案 0 :(得分:1)
实际上您的代码存在一些问题。正如Omair指出的那样,一个是ptr是一个char指针,因此cout假定它指向一个以空字符结尾的字符串。
第二个问题,正如Omair已经指出的那样,ptr [i]是一个char,它将被打印为ASCII字形而不是char的值。解决方案是将其转换为int。
另一个问题是数据的类型。由于您声明ptr指向char而不是unsigned char,因此值将被符号扩展。任何大于7F的值都将显示为FFFFFFxx(进程FF的数量取决于编译器/环境中'int'的大小),因为它在打印时从signed char转换为unsigned int。
最后一个问题(使用Omair的解决方案)是现代编译器(例如g ++ -Wall)会抱怨在void指针上进行数学运算。因此,在将ptr + i包含在pare中之前,必须先将ptr转换为void指针,然后才能进行数学运算。
完整的修正程序如下所示。
void print_bytes(myst *my_struct)
{
unsigned char *ptr = (unsigned char *)my_struct;
cout << std::hex;
for (size_t i = 0; i < sizeof(*my_struct); i++) {
cout << (const void *) (ptr + i) << ": " << (unsigned int) ptr[i] << "\n";
}
}
答案 1 :(得分:0)
cout
与函数中的printf不完全相似。要理解这里的缺陷,您需要了解<<
运算符的不同重载函数。
我们有:
ostream& operator<< (short val);
ostream& operator<< (const void* val); // prints address given a pointer
ostream& operator<< (ostream& out, const char* s ); // prints a null-terminated string
ostream& operator<< (ostream& out, const signed char* s );
ostream& operator<< (ostream& out, const unsigned char* s );
现在,我们将my_struct
转换为char *
,以便我们可以逐字节打印它。但这改变了cout
的含义,它现在需要一个空终止字符串并打印 chars ,这些都是垃圾。因此需要明确的类型转换。此外,ptr[i]
是char
,因此它只会为该值打印一个字符。
修复它:
cout << (const void *) ptr + i << ": " << (unsigned int) ptr[i];