-2

Possible Duplicate:
char pointer confusing with cout in c++

Given any structure that you would like to dump the bytes of, one way would be to implement it in C++ like so:

void print_bytes(myst *my_struct)
{
    char *ptr = (char *)my_struct;
    cout << std::hex;
    for (size_t i = 0; i < sizeof(*my_struct); i++) {
        cout << ptr + i << ": " << ptr[i];
        // similar to printf("%p: 0x%x", ptr + i, ptr[i]) right?
    }
}

but the above prints garbage both for address and value. Why?

Community
  • 1
  • 1
Omair
  • 814
  • 1
  • 10
  • 19
  • 1
    Why would you post a question, and answer your own question mere seconds after asking it? Especially since this has been answered a few times already. [Here, per example](http://stackoverflow.com/questions/10869459/char-pointer-confusing-with-cout-in-c). – netcoder Aug 03 '12 at 01:17
  • asking and answering your question is perfectly valid. In fact, while asking the question itself, there is a textbox to answer it. – Omair Aug 03 '12 at 03:05
  • Yes, the question is a duplicate of the link given by netcoder. I did not find it while writing the question. Flagged it as duplicate. – Omair Aug 03 '12 at 03:08
  • Yes, answering your own question is perfectly valid. What's odd here is that both your question and your answer have the *exact same* timestamp... – netcoder Aug 03 '12 at 13:54

2 Answers2

1

Actually there are a couple of problems with your code. One, as Omair pointed out, is that ptr is a char pointer so cout assumes it points to a null terminated string.

The second problem, again as Omair already pointed out, is that ptr[i] is a char and will be printed as the ASCII glyph rather than the value of the char. The solution is to convert it to an int.

Another problem is the type of the data. Since you declared ptr to point to char instead of unsigned char, the values will be sign extended. Any value greater than 7F will appear as FFFFFFxx (the number of proceeding FF's depends on the size of 'int' in your compiler / environment) because it is converted from signed char to unsigned int when it is printed.

One last problem (with Omair's solution) is that modern compilers (e.g. g++ -Wall) will complain about doing math on a void pointer. Therefore, you must do the math before converting ptr to a void pointer by enclosing the ptr + i in parens.

The complete corrected routine is shown below.

void print_bytes(myst *my_struct)
{
    unsigned char *ptr = (unsigned char *)my_struct;
    cout << std::hex;
    for (size_t i = 0; i < sizeof(*my_struct); i++) {
        cout << (const void *) (ptr + i) << ": " << (unsigned int) ptr[i] << "\n";
    }
}
james
  • 186
  • 1
  • 3
0

cout is not exactly similar to printf in function. To understand the pitfall here, you need to understand the different overloaded functions for << operator.

We have:

ostream& operator<< (short val);
ostream& operator<< (const void* val); // prints address given a pointer

ostream& operator<< (ostream& out, const char* s ); // prints a null-terminated string
ostream& operator<< (ostream& out, const signed char* s );
ostream& operator<< (ostream& out, const unsigned char* s );

Now, we have typecast my_struct to char * so that we can print it byte by byte. But this changes the meaning for cout and it now expects a null terminated string and prints chars which are garbage. So an explicit typecast is required. Also, ptr[i] is a char, so it just prints a single char for the value.

Fixing it:

    cout << (const void *) ptr + i << ": " << (unsigned int) ptr[i];
Omair
  • 814
  • 1
  • 10
  • 19
  • With `printf` we give explicit type conversions with the format specifier, but with `cout <<`, it is somewhat implicit. All pointers are handled the same in `cout << ` except for `char *`. – Omair Aug 03 '12 at 01:04