Topic: reinterpret_cast<char *>(&some_int)


Author: Trigve Siver <trigves@yahoo.com>
Date: Mon, 11 Oct 2010 14:07:35 CST
Raw View
Hi,
I've got the question regarding the reinterpret_cast. Is this defined
by c++0x (I mean current working draft n3126)?:

std::ifstrem input(...); // Opened as binary
....
int vaue;
input.read(reinterpret_cast<char *>(&value), sizeof(value)); // Whereinput
"has"
int

And what about reinterpret_cast<char *>(&some_pod)?

I've found this tread [1] where it said that standard doesn't say
whatever it is defined, but it is old. Maybe something has changed.
This is my original thread in c.l.c.m [2].

Thanks

Trigve

[1]
http://groups.google.com/group/comp.std.c++/browse_thread/thread/ee50864e7ed29021/ea62d566b43fd3b9?lnk=gst&q=reinterpret_cast+unsigned+char+*+to+char+*#ea62d566b43fd3b9

[2]
http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/0624841cc278fc1e#





--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Mon, 11 Oct 2010 18:06:41 CST
Raw View
On Oct 11, 9:07 pm, Trigve Siver <trig...@yahoo.com> wrote:

> I've got the question regarding the reinterpret_cast. Is this defined
> by c++0x (I mean current working draft n3126)?:

> std::ifstrem input(...); // Opened as binary
> ....
> int vaue;
> input.read(reinterpret_cast<char *>(&value), sizeof(value)); // Whereinput
> "has"
> int

It is and it isn't.  About all you can say is that you're more
or less guaranted to pass the address of the int into
input.read.  Since this function expects the address of a char
buffer, and will write it as such, just about anything can
happen after that.

> And what about reinterpret_cast<char *>(&some_pod)?

The same.

--
James Kanze

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Trigve Siver <trigves@yahoo.com>
Date: Wed, 13 Oct 2010 11:52:27 CST
Raw View
 On 12. Okt, 02:06 h., James Kanze <james.ka...@gmail.com>  wrote:
>
> It is and it isn't.  About all you can say is that you're  more
> or less guaranted to pass the address of the int into
>  input.read.  Since this function expects the address of a char
> buffer,  and will write it as such, just about anything can
> happen after  that.

Is there ANY portable way to read binary data of PODs from file?  Only
method I
can think of is using "char *" buffer and  then "std::memcpy()" to target o=
f
POD
type (3.9/2).

> > And what  about reinterpret_cast<char *>(&some_pod)?
>
> The  same.

Then what is 5.2.10/7("...When a prvalue v of type =93pointer to T1=94  is
converted
to the type =93pointer to cv T2=94, the result is  static_cast<cv
T2*>(static_cast<cv void*>(v)) if both T1 and T2  are standard-layout types
(3.9) and the alignment requirements of T2 are no  stricter than those of
T1....") good for? Could someone give some practical  example where the
sentence
above could be applied and give some defined behaviour but without the
sentence
above it wouldn't, please?

Thank  you

Trigve





--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Wed, 20 Oct 2010 16:14:17 CST
Raw View
On Oct 13, 6:52 pm, Trigve Siver <trig...@yahoo.com> wrote:
>  On 12. Okt, 02:06 h., James Kanze <james.ka...@gmail.com>  wrote:
> > It is and it isn't.  About all you can say is that you're  more
> > or less guaranted to pass the address of the int into
> >  input.read.  Since this function expects the address of a char
> > buffer,  and will write it as such, just about anything can
> > happen after  that.

> Is there ANY portable way to read binary data of PODs from file?

Unless you know the format of the data in the file, there's no
way to read it, portable or not.  If you know the format, you
read the bytes, and assemble them as the format requires.

> Only method I can think of is using "char *" buffer and  then
> "std::memcpy()" to target of POD type (3.9/2).

Which will be about the same as using reinterpret_cast.  You
will get just about anything.

> > > And what  about reinterpret_cast<char *>(&some_pod)?

> > The  same.

> Then what is 5.2.10/7("...When a prvalue v of type pointer to
> T1  is converted to the type pointer to cv T2, the result is
> static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and
> T2  are standard-layout types (3.9) and the alignment
> requirements of T2 are no  stricter than those of T1....")
> good for?

System level programming, where you have to type pun.  Nothing
portable, but you might use casts along those lines if you
wanted to extract the exponent field from a floating point, for
example.

> Could someone give some practical example where the sentence
> above could be applied and give some defined behaviour but
> without the sentence above it wouldn't, please?

The sentence you quote simply guarantees that the pointer
conversions won't result in undefined behavior.  It doesn't say
much about what happens when using the pointers, but the overall
intent is certainly that they will be well behaved for things
that are reasonable on the given architecture, and will do what
someone familiar with the architecture would expect.  Thus, to
get the exponent from a double on an Intel architecture, one
might do something like:
   int exp = (*reinterpret_cast<short*>(&d) >> 4) & 0x07FF;
   exp -= 1023;
It's not portable, of course; where the actual exponent bits
are, and how the exponent is represented, depends on the
architecture.

Any use of reinterpret_cast with regards to I/O, on the other
hand, is almost certainly an error, and in no case portable.
(On the other hand... You don't always need to be 100% portable,
and in some cases, a reinterpret_cast can be a reasonable
compromize to allow reading everything as uint32_t or uint64_t,
and using reinterpret_cast on that.  The code for reading
floating point this way is an order of magnitude simpler than
any fully portable solution -- just be aware that it will only
work on Windows and the mainstream Unixes, but not on
mainframes or a number of other machines.)

--
James Kanze

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Trigve <trigves@gmail.com>
Date: Sat, 23 Oct 2010 02:06:49 CST
Raw View
Thank you for the reply,

On 21. Okt, 00:14 h., James Kanze <james.kanze@gmail.com> wrote:
> On Oct 13, 6:52 pm, Trigve Siver <trig...@yahoo.com> wrote:
>
> >  On 12. Okt, 02:06 h., James Kanze <james.ka...@gmail.com>  wrote:
> > > It is and it isn't.  About all you can say is that you're  more
> > > or less guaranted to pass the address of the int into
> > >  input.read.  Since this function expects the address of a char
> > > buffer,  and will write it as such, just about anything can
> > > happen after  that.
> > Is there ANY portable way to read binary data of PODs from file?
>
> Unless you know the format of the data in the file, there's no
> way to read it, portable or not.  If you know the format, you
> read the bytes, and assemble them as the format requires.
>
Ok, the last example :):

std::fstream file("temp.bin", std::ios_base::in | std::ios_base::out |
std::ios_base::binary | std::ios_base::trunc);
char buffer[4];
std::int32_t value_write = 1234;
std::int32_t value_read = 0;
std::memcpy(buffer, &value_write, sizeof(value_write));
file.write(buffer, 4);
file.flush();
std::memset(buffer, 0, 4);
file.seekg(0, std::ios_base::beg);
file.read(buffer, 4);
std::memcpy(&value_read, buffer, sizeof(value_read));
assert(value_write == value_read);

Is the code above portable in following circumstances:

1 - using the code on the same platform
2 - using the code across multiple platform with same endianess
3 - using the code across multiple platform

> > Only method I can think of is using "char *" buffer and  then
> > "std::memcpy()" to target of POD type (3.9/2).
>
> Which will be about the same as using reinterpret_cast.  You
> will get just about anything.
>

Do you mean that the following code is as much portable as the code
above?:

std::fstream file("temp.bin", std::ios_base::in | std::ios_base::out |
std::ios_base::binary | std::ios_base::trunc);
std::int32_t value_write = 1234;
std::int32_t value_read = 0;
file.write(reinterpret_cast<char *>(&value_write),
sizeof(value_write));
file.flush();
file.seekg(0, std::ios_base::beg);
file.read(reinterpret_cast<char *>(&value_read), sizeof(&value_read));
assert(value_write == value_read);

Thanks

Trigve

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Joshua Maurice <joshuamaurice@gmail.com>
Date: Sat, 23 Oct 2010 13:03:53 CST
Raw View
On Oct 20, 3:14 pm, James Kanze <james.ka...@gmail.com> wrote:
> On Oct 13, 6:52 pm, Trigve Siver <trig...@yahoo.com> wrote:
>
> >  On 12. Okt, 02:06 h., James Kanze <james.ka...@gmail.com>  wrote:
> > > It is and it isn't.  About all you can say is that you're  more
> > > or less guaranted to pass the address of the int into
> > >  input.read.  Since this function expects the address of a char
> > > buffer,  and will write it as such, just about anything can
> > > happen after  that.
> > Is there ANY portable way to read binary data of PODs from file?
>
> Unless you know the format of the data in the file, there's no
> way to read it, portable or not.  If you know the format, you
> read the bytes, and assemble them as the format requires.
>
> > Only method I can think of is using "char *" buffer and  then
> > "std::memcpy()" to target of POD type (3.9/2).
>
> Which will be about the same as using reinterpret_cast.  You
> will get just about anything.
>
> > > > And what  about reinterpret_cast<char *>(&some_pod)?
> > > The  same.
> > Then what is 5.2.10/7("...When a prvalue v of type pointer to
> > T1  is converted to the type pointer to cv T2, the result is
> > static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and
> > T2  are standard-layout types (3.9) and the alignment
> > requirements of T2 are no  stricter than those of T1....")
> > good for?
>
> System level programming, where you have to type pun.  Nothing
> portable, but you might use casts along those lines if you
> wanted to extract the exponent field from a floating point, for
> example.
>
> > Could someone give some practical example where the sentence
> > above could be applied and give some defined behaviour but
> > without the sentence above it wouldn't, please?
>
> The sentence you quote simply guarantees that the pointer
> conversions won't result in undefined behavior.  It doesn't say
> much about what happens when using the pointers, but the overall
> intent is certainly that they will be well behaved for things
> that are reasonable on the given architecture, and will do what
> someone familiar with the architecture would expect.  Thus, to
> get the exponent from a double on an Intel architecture, one
> might do something like:
>    int exp = (*reinterpret_cast<short*>(&d) >> 4) & 0x07FF;
>    exp -= 1023;
> It's not portable, of course; where the actual exponent bits
> are, and how the exponent is represented, depends on the
> architecture.
>
> Any use of reinterpret_cast with regards to I/O, on the other
> hand, is almost certainly an error, and in no case portable.
> (On the other hand... You don't always need to be 100% portable,
> and in some cases, a reinterpret_cast can be a reasonable
> compromize to allow reading everything as uint32_t or uint64_t,
> and using reinterpret_cast on that.  The code for reading
> floating point this way is an order of magnitude simpler than
> any fully portable solution -- just be aware that it will only
> work on Windows and the mainstream Unixes, but not on
> mainframes or a number of other machines.)

Yay! Is comp.std.c++ back up yet? 6th try.

James, I'm not sure if you're purposefully dodging the question, or if
you genuinely do not understand the question. Yes, I am happy that we
are all better off knowing that dodgy serialization schemes are dodgy,
but that wasn't his question.

Here, let me phrase the question like this. Ignoring memory allocation
issues, stack size issues, and other QoI issues, and I guaranteed that
the following program will return 42 on a conforming implementation
(modulo typos)? If so, where is the chapter and verse saying that I
can read from and write to POD types through a char or unsigned char
lvalue obtained with a reinterpret_cast? Would the following program
work with "static_cast<char*>(static_cast<void*>(" instead of
"reinterpret_cast<char*>("?

 #include <sstream>
 using namespace std;
 int main()
 {
   int const x = 42;
   stringstream ss;
   ss.write(reinterpret_cast<char const*>(&x), sizeof(x));
   int y;
   ss.read(reinterpret_cast<char*>(&y), sizeof(y));
   return y;
 }

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Wed, 27 Oct 2010 01:22:32 CST
Raw View
On Oct 23, 9:06 am, Trigve <trig...@gmail.com> wrote:
> Thank you for the reply,

> On 21. Okt, 00:14 h., James Kanze <james.ka...@gmail.com>
> wrote:> On Oct 13, 6:52 pm, Trigve Siver <trig...@yahoo.com>
> wrote:

> > >  On 12. Okt, 02:06 h., James Kanze <james.ka...@gmail.com>  wrote:
> > > > It is and it isn't.  About all you can say is that you're  more
> > > > or less guaranted to pass the address of the int into
> > > >  input.read.  Since this function expects the address of a char
> > > > buffer,  and will write it as such, just about anything can
> > > > happen after  that.
> > > Is there ANY portable way to read binary data of PODs from file?

> > Unless you know the format of the data in the file, there's no
> > way to read it, portable or not.  If you know the format, you
> > read the bytes, and assemble them as the format requires.

> Ok, the last example :):
>
> std::fstream file("temp.bin", std::ios_base::in | std::ios_base::out |
> std::ios_base::binary | std::ios_base::trunc);
> char buffer[4];
> std::int32_t value_write = 1234;
> std::int32_t value_read = 0;
> std::memcpy(buffer, &value_write, sizeof(value_write));
> file.write(buffer, 4);
> file.flush();
> std::memset(buffer, 0, 4);
> file.seekg(0, std::ios_base::beg);
> file.read(buffer, 4);
> std::memcpy(&value_read, buffer, sizeof(value_read));
> assert(value_write == value_read);

> Is the code above portable in following circumstances:

> 1 - using the code on the same platform
> 2 - using the code across multiple platform with same endianess
> 3 - using the code across multiple platform

The code, as written, is perfectly portable, since you're
reading the data from the same process (the same compiled image)
that wrote it.  Beyond that, you should be able to read the data
from a different process if the two processes were compiled with
the "same" compiler: same version, same compilation flats,
running on the same hardware, under the same OS (although the
standard doesn't even make this guarantee).  Beyond that, all
bets are off.

> > > Only method I can think of is using "char *" buffer and  then
> > > "std::memcpy()" to target of POD type (3.9/2).

> > Which will be about the same as using reinterpret_cast.  You
> > will get just about anything.

> Do you mean that the following code is as much portable as the code
> above?:

> std::fstream file("temp.bin", std::ios_base::in | std::ios_base::out |
> std::ios_base::binary | std::ios_base::trunc);
> std::int32_t value_write = 1234;
> std::int32_t value_read = 0;
> file.write(reinterpret_cast<char *>(&value_write),
> sizeof(value_write));
> file.flush();
> file.seekg(0, std::ios_base::beg);
> file.read(reinterpret_cast<char *>(&value_read), sizeof(&value_read));
> assert(value_write == value_read);

Yep.  The two versions are, in practice, pretty much equivalent.

In practice, such hacks are fine for temporarily spilling data
to disk, to be reread later by the same process.  For anything
else, however, you need to define a format, and write it.

--
James Kanze

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]