Reputation: 780
I have the following snippet
#include <iostream>
using namespace std;
class foobar
{
public:
unsigned int a = 97;
unsigned int b = 98;
unsigned int c = 99;
};
class barfoo
{
public:
char a:32,b:32,c;
};
int main(){
foobar * f = new foobar();
barfoo * b = (reinterpret_cast<barfoo *>(f));
cout << b->a << "-" << b->b << "-" << b->c;
}
Output:
a-b-c
However, if I specify the width of c in barfoo, it doesn't work (all the values are 0). Observe
#include <iostream>
using namespace std;
class foobar
{
public:
unsigned int a = 97;
unsigned int b = 98;
unsigned int c = 99;
};
class barfoo
{
public:
char a:32,b:32,c:32;
};
int main(){
foobar * f = new foobar();
barfoo * b = (reinterpret_cast<barfoo *>(f));
cout << b->a << "-" << b->b << "-" << b->c;
}
Output:
--
The chars are all 0
Any idea why this is happening?
Link to ideone first snippet -- working
Linke to ideone second snippet -- not working
Compiler is gcc-5.1 Thanks!!
Upvotes: 0
Views: 114
Reputation: 2703
First, check if the 2 classes are even same size. Conceivably, padding and alignment may make the positions of bitfields a, b, and c different from positions of normal members a, b and c etc. Why are you using char for 32-bit bitfields? My compiler warns about bitfield exceeding size of type.
Otherwise (if you change char to unsigned int for barfoo class), regardless of any standardese-UB thrown at you, the reinterpret_cast and access has good chance of working. Maybe even more so if you use the well-supported and well-established idiom of type-punning through a union.
Type-punning through a union is a way of telling your compiler 'these 2 pointers of different types may alias, do not make radical optimizations assuming that they may not alias'.
Upvotes: 2
Reputation: 38919
This reinterpret_cast
does not meet the requirements for defined behavior, so while the assignment of it's result is acceptable any subsequent access of b
is undefined behavior:
barfoo * b = (reinterpret_cast<barfoo *>(f));
A reinterpret_cast
must meet one of these conditions, where the foobar
is the DynamicType and barfoo
is the AliasedType:
- AliasedType is (possibly cv-qualified) DynamicType
- AliasedType and DynamicType are both (possibly multi-level, possibly cv-qualified at each level) pointers to the same type T
- AliasedType is the (possibly cv-qualified) signed or unsigned variant of DynamicType
- AliasedType is an aggregate type or a union type which holds one of the aforementioned types as an element or non-static member (including, recursively, elements of subaggregates and non-static data members of the contained unions): this makes it safe to obtain a usable pointer to a struct or union given a pointer to its non-static member or element.
- AliasedType is a (possibly cv-qualified) base class of DynamicType
- AliasedType is
char
orunsigned char
: this permits examination of the object representation of any object as an array of unsigned char.
Since the AliasedType does not fall into any of these conditions the accessing of the reinterpret_cast
's result is undefined behavior.
Upvotes: 4