reinterpret_cast<>

A

Aman

Hi,
wrote this piece of code on SunOS 5.9 , compiler g++ 2.95.3

trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?


int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!
short int* spt = reinterpret_cast<short int*> (ipt) ;
cout << "spt : " << hex << spt <<endl ; // ok ---

}

regards,
Aman.
 
M

Mike Wahler

Aman said:
Hi,
wrote this piece of code on SunOS 5.9 , compiler g++ 2.95.3

trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?

It is.
int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!

The stream inserter (<<) for type 'char*' interprets the argument
as a pointer to a 'C-style' string (zero terminated array of char).
e.g.
char *p = "hello";
cout << p << '\n'; /* prints "hello" */

On of two things is happening:

- sizeof(int) on your system is four bytes, in which case none
of them has a value of zero, producing 'undefined behavior', since
cout<< will run off the end of your array.

-sizeof(int) is more than four bytes, in which case some of them
have zero value, and it appears that on your machine, a zero
is stored before any of the nonzero bytes, in which case
cout << cpt terminates before any output.

Try:

for(size_t i = 0; i < sizeof x; ++i)
cout << hex << cpt;
cout << '\n';


-Mike
 
M

Mike Wahler

Mike Wahler said:
Try:

for(size_t i = 0; i < sizeof x; ++i)
cout << hex << cpt;


We need to cast to int to get the textual representation of
the byte's value:

cout << hex << static_cast<int>(cpt);

Sorry for the oversight.

-Mike
 
R

Rob Williscroft

Aman wrote in @mygate.mailgate.org:
Hi,
wrote this piece of code on SunOS 5.9 , compiler g++ 2.95.3

trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?


int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---

The above should output the same as if you wrote:

cout << &x << endl;

i.e. the address of x, however that is printed.
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!

cout << "cpt : " << hex << unsigned(*cpt) << endl;
short int* spt = reinterpret_cast<short int*> (ipt) ;
cout << "spt : " << hex << spt <<endl ; // ok ---

As for ipt above.
#include <iostream>
#include <ostream>

int main()
{
using namespace std;
char *cpt = "test-string";
cout << cpt << endl;
}

should output test-string. i.e. the streams output a "string" for
char *'s and a memory address for other pointers.

HTH.

Rob.
 
K

kanze

The stream inserter (<<) for type 'char*' interprets the argument as a
pointer to a 'C-style' string (zero terminated array of char).
e.g.
char *p = "hello";
cout << p << '\n'; /* prints "hello" */
One of two things is happening:
- sizeof(int) on your system is four bytes, in which case none
of them has a value of zero, producing 'undefined behavior', since
cout<< will run off the end of your array.

This is his case. Doubtlessly, x is followed fairly soon by a byte
containing 0, because he doesn't get a crash, nor see any output.
(Also, the characters '\001', '\002', '\003'and '\004' don't cause any
visual display.)
-sizeof(int) is more than four bytes, in which case some of them
have zero value, and it appears that on your machine, a zero
is stored before any of the nonzero bytes, in which case
cout << cpt terminates before any output.

for(size_t i = 0; i < sizeof x; ++i)
cout << hex << cpt;
cout << '\n';


No better: cpt has type char, so he outputs the byte as a textual
char. Try:

cout << hex << static_cast< int >( cpt[ i ] ) ;

in the loop.

(And of course, the usual disclaimers concerning byte order apply: it
doesn't mean anything, there are more than two possibilities, and if you
need to know, you are doing something grieviously wrong in your code.)
 
K

kanze

Rolf Magnus said:
Makhno wrote:
Because unions are not made for such things?

And what he is doing is?

Technically, you're right, in that a union would involve undefined
behavior, where you are allowed to cast an arbitrary pointer to char* or
to unsigned char* and access the memory as an array of bytes. But a
union will work equally well in practice.

And of course, given his code, "equally well" means not at all. Which
was the purpose of his posting. Whether you use a union, or a char*
which you dereference, you must cast to int to avoid treating the char
as a character.
 
J

Jeff Schwab

Rolf said:
Makhno wrote:




Because unions are not made for such things?

It's relatively slow and/or difficult to find all uses of a union within
a set of source code, but it's easy to grep for "cast".
 
J

Jack Applin

In comp.lang.c++.moderated Aman said:
trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?

int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!

A char * is different from an int * in a crucial way: when you send a
char * to an output stream, C++ doesn't print the pointer, C++ prints
the CHARACTERS that the pointer points to!

cout << "Hello there\n";

That was a const char *, but you wouldn't expect hex, would you?

For this non-portable program, cast your char * to another pointer type:

cout << "cpt : " << hex << (void *) cpt <<endl ; // NO output for cpt !!!
 
R

Ron Samuel Klatchko

Aman said:
int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!

}

The iostream code assumes that a char* is a pointer to a string that
is '\0' terminated. So iostreams is dereferencing the pointer and
printing out each character until it finds a '\0'.

Most likely, when that bit pattern is turned into a pointer and
dereferenced, there is a '\0' byte in that place in memory.

You're lucky the code ran and did nothing instead of crashing when it
tried to dereference a random piece of memory.

samuel
 
B

Balog Pal

Aman said:
trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?

int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!
short int* spt = reinterpret_cast<short int*> (ipt) ;
cout << "spt : " << hex << spt <<endl ; // ok ---
}

Better try output wia printf

You're most likely tricked by the streams, char* is not threated as a
pointer but as a string, and is output as such. Or redirect the output to
a file and hexdump it. Or change your x init to 0x40414243

Paul
 
M

Mike Wahler

This is his case.


How do you know?
Doubtlessly, x is followed fairly soon by a byte
containing 0, because he doesn't get a crash, nor see any output.
(Also, the characters '\001', '\002', '\003'and '\004' don't cause any
visual display.)

How do you know? Remember we cannot assume a particular character set.
-sizeof(int) is more than four bytes, in which case some of them
have zero value, and it appears that on your machine, a zero
is stored before any of the nonzero bytes, in which case
cout << cpt terminates before any output.

for(size_t i = 0; i < sizeof x; ++i)
cout << hex << cpt;
cout << '\n';


No better: cpt has type char, so he outputs the byte as a textual
char. Try:

cout << hex << static_cast< int >( cpt[ i ] ) ;

in the loop.


Yes, I posted a correction almost immediately with this same code.

-Mike
 
A

Aman Angrish

Technically, you're right, in that a union would involve undefined
behavior, where you are allowed to cast an arbitrary pointer to char* or
to unsigned char* and access the memory as an array of bytes. But a
union will work equally well in practice.

that is correct . I initially tried with the union too , but got
no output because of the same reason (char* interpretation by cout) .

thanks !!
Aman.
 
F

Francis Glassborow

In message said:
Hi,
wrote this piece of code on SunOS 5.9 , compiler g++ 2.95.3

trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?


int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!

When you use 'operator <<' applied to an ostream and a char * the result
is an attempt to output a null terminated C-style string. There is no
reason to expect the bytes constituting the binary code for x to be such
a string. Indeed there are excellent reasons to suppose that it isn't.
You might also note that none of the bytes encoding x represent
printable characters in either of the common character encodings (ASCII,
EBCDIC).
 
B

Ben Hutchings

Aman said:
Hi,
wrote this piece of code on SunOS 5.9 , compiler g++ 2.95.3

trying to see the byte order of an int or short int by converting to
char* . doesn't work . the char* cpt doesn't seem to be initialized !!.
why would that be ?

There is nothing wrong with the initialisation of cpt.
int main()
{
int x=0x01020304 ;
int* ipt = &x ;
cout << "ipt : "<< hex << ipt << endl ; // ok ---
char* cpt = reinterpret_cast<char*>(ipt) ;
cout << "cpt : " << hex << cpt <<endl ; // NO output for cpt !!!

If you write a char-pointer to an ostream, it is treated as a pointer
to a null-terminated string. But cpt doesn't point to a
null-terminated string; it points to the bytes {1, 2, 3, 4} or {4, 3,
2, 1} (depending on which architecture you are running SunOS on).
which don't correspond to printable characters. Note that since these
don't include a null byte the formatting function continues to search
for a null byte in the memory after x. This has undefined behaviour,
so don't tell it to do this!

So you need to convert cpt to void * before printing it:

cout said:
short int* spt = reinterpret_cast<short int*> (ipt) ;
cout << "spt : " << hex << spt <<endl ; // ok ---

I'm not convinced that this is generally safe, because the result of
the reinterpret_cast is unspecified and so might not be convertible to
void *.

I wonder whether this program will do what you intend, even with the
output corrected. There is no guarantee that you can use *(short *)&x
to access the least significant 16 bits (or however many there are in
a short) of x, so you cannot use the value of (short *)&x to determine
where the least significant 16 bits are stored. The result of the
cast is likely to be the same address as &x, regardless of whether
the machine is big- or little-endian.

The safe way to determine byte order is to look at documentation.
Failing that, print out the bytes cpt[0] to cpt[sizeof(x)-1], but
first convert them to unsigned int so that they are treated as numbers
and not character codes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top