Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C struct padding make this use unsafe?

Suppose I have a struct, be it union'd or otherwise:

    typedef struct {
        union {
            struct { float x, y, z; } xyz;
            struct { float r, g, b; } rgb;
            float xyz[3];
        } notAnonymous;
    } Vector3;

I've heard that some compilers automatically pad structs to enhance performance by creating word-aligned boundaries.

Presumably such synergy means the size of a struct cannot be guaranteed to be the sum of its component field sizes, and therefore there is a change of data corruption and/or overflow for array xyzs in the following:

inline Vector3 v3Make(float x, float y, float z) { Vector3 v = {x,y,z}; return v; }
float xyzs[6];
*(Vector3*)&xyzs[3] = v3Make(4.0f,5.0f,6.0f);
*(Vector3*)&xyzs[0] = v3Make(1.0f,2.0f,3.0f);

Correct?

like image 630
KomodoDave Avatar asked Jan 11 '12 22:01

KomodoDave


1 Answers

It's true the compiler can lay our your structure with what ever kind of padding it wants. You can use #pragma pack or __attribute__((packed)) to avoid padding on most compilers. In practice, you have three 32-bit fields in there, so it's probably not going to be a problem. You can check by using sizeof on your structure type or a variable of that type and seeing what comes out.

What is a problem is that you're trying to assign a Vector3 to a float variable in your last two lines. That's not going to be allowed. You could hack in what you're trying to do:

*(Vector3 *)&xyzs[3] = v3Make(4.0f, 5.0f, 6.0f);

But that's pretty ugly looking, not to mention confusing. It would be a lot better to change xyzs to being an array of Vector3 rather than of just float.

like image 143
Carl Norum Avatar answered Sep 21 '22 15:09

Carl Norum