Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does cout << std::ios::hex do?

Tags:

c++

std

This question comes from a bug that I got into recently. I was trying to save some integer values to file as hex. As an example, this is what I should do:

cout << std::hex << value << endl;                 // (1)

But by mistake, I use it as the following:

cout << std::ios::hex << value << endl;            // (2) 

The compiler does not complain but obviously the result is not correct. I was trying a couple more values randomly and it seems that (2) actually give partially correct result except that it append 800 as a prefix. I don't understand where the 800 is coming from and I don't see a good reference anywhere. Can anybody explain what's happening under the hood?

cout << std::hex << 255 << endl;       // output: FF
cout << std::ios::hex << 255 << endl;  // output: 800ff

cout << std::hex << 135 << endl;       // output: 87
cout << std::ios::hex << 135 << endl;  // output: 80087

cout << std::hex << 11 << endl;        // output: b
cout << std::ios::hex << 11 << endl;   // output: 800b
like image 561
Yuchen Avatar asked Dec 01 '15 21:12

Yuchen


3 Answers

This is actually std::ios_base::hex. It's an implementation-defined bitmask. Internally, the stream has an integer called fmtflags where it stores the current state of the formatting.

In your implementation, hex is the flag 0x800. Other flags will indicate whether it's in scientific notation mode, whether boolalpha is on, etc. etc.

The std::hex function sets the std::ios_base::hex flag in fmtflags.

So your output is the integer value of this flag (in hex since you sent std::hex previously).

like image 119
M.M Avatar answered Nov 02 '22 11:11

M.M


std::hex is a manipulator, i.e., it is a function with a specific signature:

std::ios_base& hex(std::ios_base& stream) {
    stream.setf(std::ios_base::hex, std::ios_base::basefield);
    return stream;
}

There are some special output operators defined for stream to process manipulators. For the version operating on references to std::ios_base there is (ignoring that the operator is actually a function template):

std::ostream& operator<< (std::ostream& out, std::ios_base&(*manip)(std::ios_base&));

When used with a stream, the manipulator function is being called and it sets a specific format flag, in this case std::ios_base::hex (which is how std::ios::hex is actually defined). Since std::ios_base::hex is a member of a group of flags (the others are std::ios_base::dec and std::ios_base::oct) setting it also needs to clear any potential other flag in the group. Thus, setf() is called with a mask (std::ios_base::basefield) to clear any of the other potentially set flags.

The format flags std::ios_base::fmtflags is a bitmask type. The value std::ios_base::hex is one of the values. When formatting it you'll get some number, most likely a power of 2 (however, it doesn't have to be a power of 2). The value you see is simply 0x800 (i.e. 2048) printed using hex notation: setting any of the formatting flags (other than the width()) is sticky, i.e., they remain until the flag is unset. If you want to see the value 2048 (for the implementation you are using) you'd use

std::cout << std::dec << std::ios_base::hex << "\n";      // 2048
std::cout << std::hex << std::ios_base::hex << "\n";      // 800
std::cout << std::showbase << std::ios_base::hex << "\n"; // 0x800

The last line sets the flag showbase which indicates the base of an integer value with a prefix:

  • no prefix => decimal
  • a leading 0x => hexadecimal
  • a leading 0 (but no x) => octal
like image 26
Dietmar Kühl Avatar answered Nov 02 '22 10:11

Dietmar Kühl


std::hex is a special object that, when applied to a stream using operator<<,

sets the basefield of the stream str to hex as if by calling str.setf(std::ios_base::hex, std::ios_base::base field)

std::ios::hex (aka std::ios_base::hex) is the actual bitmask value that gets passed to the setf method. Its value is implementation defined, and it seems to be 0x800 in your case.

like image 6
Tristan Brindle Avatar answered Nov 02 '22 10:11

Tristan Brindle