'use reinterpret_cast to group neighbored values together' defined inc++ standard?

F

familiewie

A quick example:
struct vec {
long d[2];
};

struct segment {
vec A, B;
};

struct polygon {
vec* points;

polygon(unsigned int size) { points=new vec[size]; }
~polygon() { delete[] points; }
};

int main() {
polygon test(4);
test.points[0][0] = 1; test.points[0][1] = 2;
test.points[1][0] = 3; test.points[1][1] = 4;
test.points[2][0] = 5; test.points[2][1] = 6;
test.points[3][0] = 7; test.points[3][1] = 8;
segment *border = reinterpret_cast<segment*>(test.points);
for(int i=0; i<3; ++i){
std::cout << '(' << border->A.d[0] << ", " << border->A.d[1] << "), (" << border->B.d[0] << ", " << border->B.d[1] << ')' << std::endl;
border = reinterpret_cast<segment*>(reinterpret_cast<char*>(border) + sizeof(vec));
}
}

This example works in Visual Studio. Does it also work with any other c/c++ compiler? Meaning is this usage of pointers, well defined in the c/c++ standards or is this plattform/compiler specific?

Thanks for any answer.
 
I

Ian Collins

A quick example:
struct vec {
long d[2];
};

struct segment {
vec A, B;
};

struct polygon {
vec* points;

polygon(unsigned int size) { points=new vec[size]; }
~polygon() { delete[] points; }
};

int main() {
polygon test(4);
test.points[0][0] = 1; test.points[0][1] = 2;

These lines shouldn't compile.
test.points[1][0] = 3; test.points[1][1] = 4;
test.points[2][0] = 5; test.points[2][1] = 6;
test.points[3][0] = 7; test.points[3][1] = 8;
segment *border = reinterpret_cast<segment*>(test.points);

reinterpret_cast is a bunt instrument that just tells the compiler to
interpret a bunch of bits as a particular type. There isn't any type
checking and the types don't have to be related. You could have written

int *border = reinterpret_cast<int*>(test.points);

and it would have compiled.
This example works in Visual Studio. Does it also work with any other c/c++ compiler? Meaning is this usage of pointers, well defined in the c/c++ standards or is this plattform/compiler specific?

Please remember to wrap your lines are remove the other cap that awful
google interface adds to your replies!
 
F

familiewie

First thank you for your answer, but you misunderstood me.

I do know that my example will compile with any compiler.

I wanted to know, if this mini programm does work exactly the same (with the same outputs), when I compile it with different compilers.
 
F

familiewie

Ups, I just realized, that this does not compile correctly. That is, because I quickly extracted the code from my project.

Here is the corrected version:

#include <iostream>

struct vec {
long d[2];
};

struct segment {
vec A, B;
};

struct polygon {
vec* points;

polygon(unsigned int size) { points=new vec[size]; }
~polygon() { delete[] points; }
};

int main() {
polygon test(4);
test.points[0].d[0] = 1; test.points[0].d[1] = 2;
test.points[1].d[0] = 3; test.points[1].d[1] = 4;
test.points[2].d[0] = 5; test.points[2].d[1] = 6;
test.points[3].d[0] = 7; test.points[3].d[1] = 8;
segment *border = reinterpret_cast<segment*>(test.points);
for(int i=0; i<3; ++i){
std::cout << '(' << border->A.d[0] << ", " << border->A.d[1] << "), (" << border->B.d[0] << ", " << border->B.d[1] << ')' << std::endl;
border = reinterpret_cast<segment*>(reinterpret_cast<char*>(border) + sizeof(vec));
}
return 0;
}
 
I

Ian Collins

(e-mail address removed) wrote:

Please wrap your lines!
First thank you for your answer, but you misunderstood me.

I do know that my example will compile with any compiler.

I wanted to know, if this mini programm does work exactly the same
(with the same outputs), when I compile it with different compilers.

As posted, it won't compile with any compiler.

As I said in my reply (that you forgot to quote), all reinterpret_cast
does is tell the compiler to interpret a bunch of bits as a particular
type. If the data pointed to happens to be of a compatible type and
alignment, it will probably work. If not, it won't.
 
F

familiewie

Quote: Please wrap your lines!

Sorry, what does that mean, English is not my native language?
 
I

Ian Collins

Quote: Please wrap your lines!

Sorry, what does that mean, English is not my native language?

That awful google Usenet interface doesn't add any line breaks (like
this client has), so those of us who use normal news readers have to
scroll along your lines or manually re-wrap them.

Just add a return every 70-80 characters and you'll be doing us a favour.
 
G

Gerhard Fiedler

Ian said:
That awful google Usenet interface doesn't add any line breaks (like
this client has), so those of us who use normal news readers ...
^^^^^^

"normal" (in this context) === "lacking in functionality" (in a "normal"
context)? :)

I'm using a "normal" news reader that can display long lines just fine
for me to read without scrolling. We've come a long way from the
1980s... When I read stuff like this I feel like the guy who came from
the future :)

Who knows, you may even throw together a C++ program that adds this
lacking functionality to your news reader (to get back almost on topic
:)

Gerhard
 
B

Bart van Ingen Schenau

struct segment {
vec A, B;
};
segment *border = reinterpret_cast<segment*>(test.points);
for(int i=0; i<3; ++i){
std::cout << '(' << border->A.d[0] << ", " << border->A.d[1] << "),
(" << border->B.d[0] << ", " << border->B.d[1] << ')' << std::endl;
border = reinterpret_cast<segment*>(reinterpret_cast<char*>(border)
+ sizeof(vec));
}
return 0;
}

The results of this program are not defined by the C++ language. By using
reinterpret_cast and dereferencing the result, you have placed yourself
completely at the mercy of the implementation.

Although they are unlikely to take advantage of it, an implementation is
allowed to put padding between the A and B members of segment, which
would cause your code to fail.

Bart v Ingen Schenau
 
M

Marcel Müller

The results of this program are not defined by the C++ language. By using
reinterpret_cast and dereferencing the result, you have placed yourself
completely at the mercy of the implementation.

Although they are unlikely to take advantage of it, an implementation is
allowed to put padding between the A and B members of segment, which
would cause your code to fail.

In fact he expected that segment and vec share a binary compatible
memory layout. This is not guaranteed.

But what about

struct segment {
vec v[2];
};

or optionally

struct segment {
vec v[2];
vec& A() { return v[0]; }
vec& B() { return v[1]; }
};

I think this should be safe since the cast now goes to an array slice.


Marcel
 
M

Marek Borowski

(e-mail address removed) wrote:

Please wrap your lines!


As posted, it won't compile with any compiler.

As I said in my reply (that you forgot to quote), all reinterpret_cast
does is tell the compiler to interpret a bunch of bits as a particular
type.
We can assume that everybody knows that.
If the data pointed to happens to be of a compatible type and
alignment, it will probably work. If not, it won't.
Question should be if there is guarantee that data placement is done in
the same way among different compilers. If not reinterpret_cast is not
portable at all.

Regards

Marek
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top