Jump to content
  • Advertisement
Sign in to follow this  
Mantear

Casting a structure, C++

This topic is 4336 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Greetings! In C++, I have a structure that contains 4 unsigned chars. I have a function that takes a pointer to unsigned chars. Is it guaranteed for the following to work?
MyStruct A; // Contains only 4 unsigned chars
MyFunction(reinterpret_cast<unsigned char*>(&A));
I realize that if I'm using reinterpret_cast that there is probably a better way to do it. For the sake for argument, assume that MyFunction is part of an API that I cannot change. Thanks!

Share this post


Link to post
Share on other sites
Advertisement
Assuming that the memory layout of your structure is:

struct MyStruct
{
unsigned char a, b, c, d;
};


Then you did the Right ThingTM. API-interaction is one of the few situations where C idioms are used in C++, and using reinterpret_cast instead of a plain C cast was a very good (and readable) take on the issue.

Of course, if the layout is:
struct MyStruct
{
unsigned char a[4];
};


Then no conversion is necessary.

Share this post


Link to post
Share on other sites
I don't believe it is guaranteed by standard, but it should work as expected under most (if not all) compilers using default struct alignment.

It would probably be better to have something like the following, however:


struct MyStruct
{
unsigned char myChars[4];
}



Then call MyFunction like so:

MyStruct A;
MyFunction(A.myChars);



Edit: Ah, late. :P
So is it technically *guaranteed* in the case of your first struct example, ToohrVyk? There obviously isn't a reason for that struct to have any other memory layout than that of an array of 4 unsigned chars, but is that standard-defined?

Share this post


Link to post
Share on other sites
I believe, IIRC, that yes, this should work under the following conditions:

1) The Structure must not have any virtual functions (remember, structs in C++ are just a class with public visibility by default) in which case The first element may (will?) be a pointer to the vTable.

2) You should also specify byte-wide packing for the struct, for which you'll need to consult your compiler's manual. Under Microsoft's compiler, I believe the command is "#pragma pack(1)" or somesuch. In your specific case, it should be fine, as this only really comes into play when differently sized members are involved, but a compiler may re-order the following struct to save space under defualt allignment:


struct stuff {
public:
unsigned char a;
unsigned short b;
unsigned char c;
};




If the compiler does re-pack the members, it should come out as "a,c,b" in this case.


Also of note, I beleive that the standard only specifies that members are declared in order within their respective visibility (Allowing for alignment, as in #2 above) but that no order between visibilities is enforced. For example:


struct stuff {
public:
int x;
int y;
private:
int width;
int height;
};




IIRC, the standard says that (Again, allowing for alignment) y must follow x, and that height must follow width, but allows that the private members *could* be placed before the public ones, it's implimentation dependant. However, AFAIK, all implimentations simply allocate space for the members in the order they are encountered. As long as you're only using one visibility level its a moot point.

Failing all of this, if you're not concerned with having portable behavior you can simply place some marker values in each of the unsigned chars and then look at the bits while debugging to confirm the layout.


Take this with a grain of salt, I'm recalling all this from a somewhat vague memory of a discussion that took place on here probably a year ago. There are members of this forum that are far more knowlegable off the more essoteric parts of the C++ standard than I.

Share this post


Link to post
Share on other sites
@ ToohrVyk: Yes, my structure is similar to what you first described. 4 unsigned chars individually declared within the struct, with nothing else in it.

I just want to make sure that reinterpret_cast<unsigned char*>(&A) is legitimate and guaranteed to function as expected according to the standard. I don't like reading out of the structure into an unsigned char array and then calling the function, but I'd rather do that if the casting is not always going to work/be safe.

Share this post


Link to post
Share on other sites
well if you know specifically what you want it to cast to, you can use the

operator <type> () operator inside the class


struct MyStruct
{
unsigned char a[4];

operator unsigned char* ()
{
return &a[0];
};
};

MyStruct a;

// Then just call
MyFunction(a);




Share this post


Link to post
Share on other sites
Found this in the standard:
Quote:
[ISO/IEC 14882 9.2.17]
A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member
As this behaviour is guaranteed for POD types, of which MyStruct is one, the only potential problem now is with the alignment of the chars in the struct.

I don't believe struct member alignment is standard-defined, but (almost) all compilers will align each character on a sizeof(char) boundary within the struct, so relying on using a pointer to this sequence of characters (and therefore relying on the behaviour that after incrementing a pointer to A that's been reinterpreted as a char pointer, the pointer will point to the second char of A) is "guaranteed" to work on the vast majority of compilers out there, but I don't believe it is standard-defined behaviour.

My knowledge of the standard is far from perfect so corrections are very much welcome.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!