Tarang Jain
Tarang Jain

Reputation: 35

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

I have a printf statement as:

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

How do I write this statement using std::cout? Buffer variables contains huge addresses.

Upvotes: 2

Views: 895

Answers (2)

Jaffa
Jaffa

Reputation: 12700

You can use the std::setw, std::setfill and std::hex modifiers:

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

Notes:

  • std::setw resets after printing something
  • As noted by Tarang Jain, std::showbase would place the base marker inside the filling (i.e. 000xDEAD instead of 0x0000DEAD) so I edited this answer to reflect this.
  • You may need to #include <iomanip>
  • It may be a good idea to wrap this iomanips between std::ios_base::fmtflags f{cout.flags()}; to save the flags and cout.flags(f); to reset them to their former values, see this question for more information
  • This answer provides a way to display things using iomanips, see also Jerry Coffin's answer to simply print a memory address

A more complete example, using an object to leverage RAII to clear the flags

#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);

  // ...
}

Upvotes: 4

Jerry Coffin
Jerry Coffin

Reputation: 490108

What you're doing in C is (apparently) casting the pointers to an unsigned integer type, then printing out that value in hexadecimal.

C++, however, provides a conversion specifically for pointers:

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

On most typical current implementations, this will probably produce pretty much the same result (i.e., an unsigned number in hexadecimal, probably zero-filled to produce the width of the addressing on the target system).

Since this is more abstract, it can adapt to the conventions of the target system. One target system might normally omit the leading 0x. Another might normally use octal instead of hexadecimal. And, of course, it won't usually print out a 64-bit address on a system that uses 32-bit addressing. Instead, this can produce the accepted convention on the system you target, instead of your explicitly specifying one convention that happens to match the systems to which you're accustomed.

Upvotes: 1

Related Questions