0x%08lx printf 语句中的格式说明符到 cout

0x%08lx format specifier in printf statement to cout

我有一个 printf 语句:

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

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

您可以使用 std::setw, std::setfill and std::hex 修饰符:

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

备注:

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

一个更完整的例子,使用一个对象来利用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);

  // ...
}

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

然而C++提供了专门针对指针的转换:

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

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

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