【问题标题】:0x%08lx format specifier in printf statement to cout0x%08lx printf 语句中的格式说明符到 cout
【发布时间】:2020-09-30 17:32:47
【问题描述】:

我有一个 printf 语句:

printf("Buffer A Data: 0x%08lx, Buffer B Data: 0x%08lx\n\n", (ul) bufa, (ul) bufb);

如何使用std::cout 编写此语句?缓冲区变量包含巨大的地址。

【问题讨论】:

    标签: c++ hex printf cout


    【解决方案1】:

    您可以使用std::setwstd::setfillstd::hex 修饰符:

    std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0') << bufa;
    

    注意事项:

    • std::setw 打印后重置​​
    • 正如Tarang Jain 所指出的,std::showbase 会将基本标记放置在填充物内(即000xDEAD 而不是0x0000DEAD)所以我编辑了这个答案以反映这一点。
    • 您可能需要#include &lt;iomanip&gt;
    • std::ios_base::fmtflags f{cout.flags()};cout.flags(f); 之间包装此iomanip 以将其重置为以前的值可能是个好主意,请参阅this question 了解更多信息
    • 此答案提供了一种使用 iomanips 显示内容的方法,另请参阅 Jerry Coffin's answer 以简单地打印内存地址

    一个更完整的例子,使用一个对象来利用RAII来清除标志

    #include <iomanip>
    #include <ostream>
    
    struct addressPrinter
    {
      addressPrinter(std::ostream& out)
      : out{out}, flags{out.flags()}
      {
      }
    
      ~addressPrinter()
      {
        out.flags(flags);
      }
    
      void print(unsigned long address)
      {
        out << "0x" << std::hex << std::setw(8) << std::setfill('0') << address;
      }
    
      std::ostream& out;
      std::ios_base::fmtflags flags;
    };
    
    void foo()
    {
      // ...
    
      addressPrinter printer{std::cout};
    
      printer.print(bufa);
      printer.print(bufb);
    
      // ...
    }
    

    【讨论】:

    • 值得一提的是 setw 必须为第二个变量重复,但其他操纵器不需要。
    • 使用printf语句的实际输出为:0x0000000111ffd000,而使用std::cout 给出输出:** 000000x111ffd000**
    • @TarangJain 好点,让我更新我的答案以反映这一事实!
    【解决方案2】:

    您在 C 中所做的是(显然)将指针转换为无符号整数类型,然后以十六进制打印出该值。

    但是,C++ 提供了专门针对指针的转换:

    std::cout << "Buffer A Data: " << static_cast<void *>(bufa) 
              << ", Buffer B Data: " << static_cast<void *>(bufb) << "\n\n";
    

    在大多数典型的当前实现中,这可能会产生几乎相同的结果(即,十六进制的无符号数,可能用零填充以产生目标系统上的寻址宽度)。

    由于这个比较抽象,可以适应目标系统的约定。一个目标系统通常会省略开头的0x。另一个可能通常使用八进制而不是十六进制。当然,它通常不会在使用 32 位寻址的系统上打印出 64 位地址。相反,这可以在您的目标系统上产生公认的约定,而不是您明确指定一个恰好与您习惯的系统匹配的约定。

    【讨论】:

    • 谢谢,我在我的回答中添加了对您的回答的参考:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-16
    • 1970-01-01
    • 2012-05-17
    • 2012-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多