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

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

本文关键字:语句 cout printf 格式 说明符 0x%08lx      更新时间:2023-10-16

我有一个printf语句:

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

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

您可以使用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 <iomanip>
  • 将此
  • iomanips 包装在std::ios_base::fmtflags f{cout.flags()};以保存标志和cout.flags(f);将它们重置为以前的值之间可能是个好主意,有关更多信息,请参阅此问题
  • 这个答案提供了一种使用 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) << "nn";

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

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