views:

198

answers:

4
 void* GetData()
 {
    return reinterpret_cast<unsigned char*>(this);
 }

Is there a case of automatic type coercion happening in this case ??? How could I convert the object of my class to an unsigned char* ??

+6  A: 

I assume you refer to return reinterpret_cast<unsigned char*>(this);

This is a nasty chunk that is probably taking the wrong approach in solving the wrong problem. Technically, it asks the compiler to re-interpret the type of the this pointer as an unsigned char* pointer. No work is done here: the statement only instructs the compiler to think of the pointer as of a different type. This is disastrous if it's wrong to interpret the type as such.

If you wish to inspect your object bitwise then you might try something like this:

union inspect_klass {
    klass obj;
    char bits[sizeof(klass)];
};

EDIT: My confidence about the above union is shaken now. Don't use it just yet, I'm looking for confirmation that this trick is indeed broken. :s

wilhelmtell
Inspecting a class through union is undefined behavior, though: http://stackoverflow.com/questions/2310483/purpose-of-unions-in-c-and-c
Cubbi
Oh my. From the standard's draft, section 9.5 paragraph 1: ... _"The size of a union is sufficient to contain the largest of its data members."_ Can anyone please confirm I'm getting this right: This means that in the union code above the union's size may be larger than the size of either of its (size-equivalent) members. Not only that, but the two members may then be aligned differently from each other.
wilhelmtell
@Wilhelm Alignment aside, the standard says that once you have accessed a union by one of its members, accessing it via the other is undefined behaviour. Of course, the trick is very widely used, but that's what the standard says.
anon
@Neil can you refer me to where exactly the standard says that?
wilhelmtell
Curious...what's allowed in a union type has changed dramatically w/ C++0x. For instance, all reference to POD types have been removed - you can now store non POD types in a union. 9.5.1 has this to say: "In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time." Curious that the entire union spec doesn't mention access or another type, only storage.
Nathan Ernst
9.5.2 is a very interesting read now: "if any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union."
Nathan Ernst
A: 

First off, your GetData() return type does not match the return type of the expression.

reinterpret_cast is similar to old an old style C cast - you are simply returning a pointer to a unsigned char*. It is completely unsafe. In effect, you are creating a view into the data of a class, which can be accessed byte-wise.

Yann Ramin
+1  A: 

I agree with the other posts: this is almost certainly not what you intend to do.

However, IIRC, you are guaranteed by the C++ standard to be able to convert a pointer of any type (not including function or member pointers) to an unsigned char * or a void * and back without entering the realm of undefined behavior. Additionally, you may access any object through an lvalue of type char * or unsigned char * (see ISO 14882:2003 section 3.10.15). I have made use of this before in order to inspect the internal representation of arbitrary object types. This results, if my reading of the standard is correct, in "implementation-defined behavior" (obviously, the internal representation of types depends upon the implementation).

For example,

template<class T> std::vector<unsigned char> to_bytes (const T& t)
{
    const unsigned char *p = reinterpret_cast<const unsigned char *>(&t);
    return std::vector<unsigned char>(p, p + sizeof(T));
}

is a template function that will yield a std::vector<unsigned_char> which is a copy of the object's internal representation.

However, the fact that you cast to void * when you return makes me suspect you are doing something perhaps more unsavory and more undefined.

Derrick Turk
You can make this function more efficient if you take iterators or a vector by reference, rather than return a vector. Still, I can't help but wonder if there's a safe, proper way to get this done at compiletime, with no dynamic-allocation.
wilhelmtell
A: 

Strictly speaking, unsigned char* is a byte array. It seems like a perfectly logical thing to do if the caller is going to serialize the data.

David Good
There are ways to serialize objects. This is not a good way to do that. It's dangerous: the client better know exactly how many bytes to read when it reconstructs the object. C++ gives you higher-level ways to do that, so you are less prone to error. Then of course there are libraries such the boost serialization library.
wilhelmtell
There's no mention at all about the scope of the function. If it's anything other than private I agree with you. Doesn't mean whomever wrote it didn't intend to serialize it.
David Good