简体   繁体   中英

hex << setw() << setfill() doesn't work with pointer value output

Win7 - 64
cygwin
Netbeans 7.4
gcc (cygwin) 4.8.3

Compiler call

g++ -Wall -Wno-reorder -Wno-unused-value -c -g -MMD -MP -MF

Any reason that the output and the expected output are different? I did not expect the "0x" prefix.

Output   << SlipHashEntry::create      0x22a000 list3
Expected << SlipHashEntry::create      0x000000000022a000 list3

Output   << SlipDescription::delete    0x600062d50 list5
Expected << SlipDescription::delete    0x0000000600062d50 list5

Here's the relevant code snippet

SlipHashEntry::SlipHashEntry
    ( const string& name, void* ptr, Type type, int debugFlag )
: completeFlag(false)
, debugFlag(debugFlag)
, hashDebugFlag((bool)(debugFlag & SlipRead::HASH))
, inputDebugFlag((bool)(debugFlag & SlipRead::INPUT))
, leakDebugFlag((bool)(debugFlag & SlipRead::LEAK))
, descriptorChain(NULL)
, link(NULL)
, name(new string(name))
, nestedPtr(NULL)
, ptr(ptr)
, type(type) { 
    DEBUG(leakDebugFlag,
    cout << left << setw(27) << setfill(' ') << "SlipHashEntry::create " 
         << hex << setw(sizeof(void*)) 
         << setfill('0') << (void*)this << ' ' << name <<endl;)
}; 

"Any reason that the output and the expected output are different? I did not expect the "0x" prefix."

Regarding the 0x prefix in the output, this is done by the intrinsic operator overload for std::ostream& operator<<(std::ostream&, const void*) see (7)

Also you have a little misconception about the setw() : You should remember, that setw() sets the fieldsize in characters (ie digits). You want to display a 64-bit pointer which is equivalent to 8 bytes with 2 digits for representation of each byte

      cout << left << setw(27) << setfill(' ') << "SlipHashEntry::create " 
           << hex << setw(2 * sizeof(void*)) 
                       // ^^^
           << setfill('0') << (void*)this << ' ' << name <<endl;)

just multiply the pointer size (in bytes) by 2, to get the correct field width for the full number of digits.

Though the intrinsic output operator definition for void* doesn't exactly do what you want.
When I've been trying to make an online compilable sample for what I was stating above, I noticed that you can't actually manipulate the intrinsic pointer output format. I have made up a simple sample, how to achieve the fixed 8 byte format you want:

#include <iostream>
#include <iomanip>

// A simple manipulator to format pointers in a fixed length format (according 
// 64 bit) with leading zeroes and a "0x" prefix
class fmt_longptr {
public:
    fmt_longptr(void* ptr) : ptr_(ptr) {}
    void put(std::ostream& os) const {
        os << "0x" << std::hex << std::setw(2 * sizeof(void*)) 
           << std::setfill('0') << (unsigned long)ptr_;
    }
private:
    friend std::ostream& operator<<(std::ostream& os, const fmt_longptr& fmt);
    void* ptr_;
};

std::ostream& operator<<(std::ostream& os, const fmt_longptr& fmt) {
    fmt.put(os);
    return os;
}

Here's how to use it, and showing what the difference vs the intrinsic pointer formatting is

int main() {
    int a;

    std::cout << std::setfill('0') << std::setw(2 * sizeof(void*)) << &a 
              << std::endl;
    std::cout << fmt_longptr(&a) << std::endl;
    return 0;
}

Output

000x7fff270d987c
0x00007fff270d987c

Here's the working online sample .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM