【问题标题】:cout << tricky operator overloading - dumping bytes of a structure [duplicate]cout << 棘手的运算符重载 - 转储结构的字节 [重复]
【发布时间】:2012-08-03 01:00:16
【问题描述】:

可能重复:
char pointer confusing with cout in c++

给定任何你想转储字节的结构,一种方法是在 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?
    }
}

但是上面的打印地址和值都是垃圾。为什么?

【问题讨论】:

  • 你为什么要发布一个问题,并在提出问题几秒钟后回答你自己的问题?特别是因为这已经回答了几次了。 Here, per example.
  • 提出并回答您的问题是完全有效的。实际上,在问问题本身的同时,还有一个文本框可以回答它。
  • 是的,问题是netcoder给出的链接的副本。我在写问题时没有找到它。将其标记为重复。
  • 是的,回答您自己的问题是完全有效的。奇怪的是,您的问题和答案都具有完全相同时间戳...

标签: c++ printf cout


【解决方案1】:

实际上,您的代码存在一些问题。正如 Omair 指出的那样,一个是 ptr 是一个 char 指针,因此 cout 假定它指向一个以空值结尾的字符串。

正如 Omair 已经指出的,第二个问题是 ptr[i] 是一个字符,并且将打印为 ASCII 字形而不是字符的值。解决方案是将其转换为 int。

另一个问题是数据的类型。由于您声明 ptr 指向 char 而不是 unsigned char,因此这些值将被符号扩展。任何大于 7F 的值都将显示为 FFFFFFxx(进行中的 FF 的数量取决于编译器/环境中 'int' 的大小),因为它在打印时会从有符号字符转换为无符号整数。

最后一个问题(使用 Omair 的解决方案)是现代编译器(例如 g++ -Wall)会抱怨在 void 指针上进行数学运算。因此,您必须在将 ptr 转换为 void 指针之前进行数学运算,方法是将 ptr + i 括在括号中。

完整的修正程序如下所示。

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";
    }
}

【讨论】:

    【解决方案2】:

    cout 在功能上与 printf 不完全相同。要了解这里的陷阱,您需要了解&lt;&lt; 运算符的不同重载函数。

    我们有:

    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];
    

    【讨论】:

    • 对于printf,我们使用格式说明符进行显式类型转换,但对于cout &lt;&lt;,它有点隐含。除了char * 之外,所有指针在cout &lt;&lt; 中的处理方式相同。
    猜你喜欢
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多