6
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    char array[10];

    for(int i = 0; i<10;i++)
    {
        array[i] = 'a' + i;
    }

    char* test = array;

    printf("%x\n", test);
    cout << hex << test << endl;

}

The output for this is:

bffff94e
abcdefghijN???

Why is it not printing the same thing?

Eitan T
  • 32,660
  • 14
  • 72
  • 109
ordinary
  • 5,943
  • 14
  • 43
  • 60
  • 1
    If you want to print a pointer, you should use `%p` with `printf()`, `%x` is for an unsigned hexadecimal integer. Like `%x`, `std::hex` doesn't work as you expect with pointers, it aims to be use with integral numerical values. – Guillaume Papin Jun 19 '12 at 07:21

4 Answers4

7
cout << hex << test << endl; 

It prints the string, not the address. It is because there is an overload of operator<< which takes char const* as argument and this overload treats the argument as string.

If you want to print the address, cast the argument to void* so that other overload of operator<< will be invoked which will print the address.

cout << hex << static_cast<void*>(test) << endl;

will print the address, in hexadecimal format.

Note that hex stream-manipulator is not needed here, as the address will be printed in hexadecimal format anway. So

cout << static_cast<void*>(test) << endl;

is enough.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Would `&test` instead of `(void *) test` not work just as well (and look a bit less daunting to a [perhaps] newer programmer)? (Forgive me if I am wrong here; I don't work in C++ too much.) – Zéychin Jun 19 '12 at 06:48
  • 2
    @Nawaz Wrong. `&test` prints something else. Your example uses an *array*, not a *pointer*, which is why it works but OP uses a pointer. Also, please get rid of these C-style casts. We have a broad consensus that they shouldn’t be used, which makes them even more harmful in teaching material (= here). – Konrad Rudolph Jun 19 '12 at 06:54
  • @KonradRudolph: Ohh.. you're right. (now please remove the downvote :D) – Nawaz Jun 19 '12 at 06:55
  • @KonradRudolph: c-style casts are good here. It is short and cute. It's application cannot harm here. – Nawaz Jun 19 '12 at 06:56
  • The answer is good, except for the C-style cast (which is why I don't upvote either). A lot of newcomers might just copy-paste blindly such answers and we will never get rid of these ambiguous C-style cast in bigger codebases. – ereOn Jun 19 '12 at 07:04
  • 1
    Just for the record, I don't have anything against C style casts in this specific case (but generally, I restrict them to numeric values, and ban them on pointers---accepting them for `(void*)` in an output statement is an exception. – James Kanze Jun 19 '12 at 07:49
  • 1
    Note that the response is wrong on several counts. For starters, and most importantly, you really should point out that the original has several cases of undefined behavior. And secondly, there's no guarantee that outputting a pointer will result in hex. I've worked on machines where it was octal, and on one of the most widespread machines a few years back, it had the format `XXXX:XXXX` (where XXXX _was_ hexadecimal). And the `hex` modifier isn't required to have any effect on a `void*`; you could get octal even with it. – James Kanze Jun 19 '12 at 07:52
6

Because your program has undefined behavior. And because you ask it to print different things.

Your invocation of printf is illegal, and results in undefined behavior (and is a good example of why you should never use printf). Your format specifier says to extract an unsigned int from the argument list, and output that in hexadecimal. Passing it anything but an unsigned int is undefined behavior. As it happens, given the way varargs are generally implemented, if you're on a machine where unsigneds and pointers have the same size, you'll probably output the value of the pointer, treating its bits as if it were an unsigned. Other behaviors are certainly possible, however. (If I'm not mistaken, g++ will warn about this construct; it's also possible that on some platforms, it will crash.)

In the case of std::cout, you're passig it a char*. By definition, the char* is treated as a '\0' string, not as a pointer (and certainly not as an unsigned int). And again, you have undefined behavior, since your char* doesn't point to a '\0' terminated string; you never put a '\0' at the end. (This probably explains the "N???" you see at the end of your output. But again, undefined behavior is, well, undefined. The code could just as easily have crashed.)

Finally, you're using both printf and std::cout; the results are not really specified unless you do a flush of the stream between the two. (In practice, if you're outputting to an interactive device, the flush should occur when you output the '\n' character. If you redirect the output to a file, however, you're likely to get something different.)

It's not clear what you want. If you want to output the address of array, it would be:

printf( "%p\n", test );
std::cout << static_cast<void*>( test ) << std::endl;

If you want to output the string you've generated, then append a '\0' to the end of it (without overflowing the buffer), and then:

printf( "%s\n", test );
std::cout << test << std::endl;

I'm not sure what you're trying to make "hex"; there is no such thing as a hex representation of a string, and the representation of a pointer is implementation defined, and not required to take into account any formatting parameters in iostream. (Typically, on most modern machines, it will be hex. But I've worked on more than a few where it would be octal, and at least one where it wouldn't be just a number, regardless of the base.) If you want a hex dump of array, you'll have to loop, outputting each value as an unsigned in hex:

for ( int i = 0; i < 10; ++ i ) {
    printf( "%x", static_cast<unsigned char>( test[i] ) );
}
printf( "\n" );
std::cout.setf( std::ios_base::hex, std::ios::basefield );
for ( int i = 0; i < 10; ++ i ) {
    std::cout << static_cast<unsigned>( static_cast<unsigned char>( test[i] ) );
}
std::cout.setf( std::ios_base::dec, std::ios::basefield );
std::cout << std::endl;

Finally: a word about the casts: plain char may be either signed or unsigned; if it is signed, converting it to an int or an unsigned, might produce either a negative value (int) or a very large positive value (unsigned). Thus, the first conversion to unsigned char, which guarantees a result in the range [0, UINT_MAX]. Second, of course, we have to convert the unsigned char to unsigned:

  • in the case of printf, because we would otherwise have undefined behavior, but the conversion is implicit, since passing an unsigned char as a vararg automatically promotes it to unsigned; and

  • in the case std::cout, because the rules are that any character type be output as a character, not as a numerical value (and since the type is used here in function overload resolution, and is not being passed to a vararg or an unsigned, there is no implicit conversion).

James Kanze
  • 150,581
  • 18
  • 184
  • 329
2

test itself is a pointer, i.e. it stores an address. Your printf statement prints the hexadecimal value of that address.

The cout << statement then prints the entire string, because the std::hex manipulator does not affect the way strings are printed. It only affects the way integers are printed.

What you can do is

  1. Loop through the characters of the array
  2. Convert each to an integer and print using the std::hex manipulator

That would look like this:

for (int i = 0 ; i < 10 ; ++i)
  std::cout << std::hex << static_cast<int>(array[i]) << '\n';
jogojapan
  • 68,383
  • 11
  • 101
  • 131
0

cout << HEX <<
can't be used to a char* to print a hex char string, but you can use it for int ,double,float,etc.

And, as you second print, why the string has some garbled strings is that you haven't gived a '\n' to the string which means the end of string

Botz3000
  • 39,020
  • 8
  • 103
  • 127
canvas
  • 1