#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?
In C programming language, hexadecimal value is represented as 0x or 0X and to input hexadecimal value using scanf which has format specifiers like %x or %X.
You can print a pointer value using printf with the %p format specifier. To do so, you should convert the pointer to type void * first using a cast (see below for void * pointers), although on machines that don't have different representations for different pointer types, this may not be necessary.
The first nine numbers (0 to 9) are the same ones commonly used in the decimal system. The next six two-digit numbers (10 to 15) are represented by the letters A through F. This is how the hex system uses the numbers from 0 to 9 and the capital letters A to F to represent the equivalent decimal number.
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.
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
unsigned
s 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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With