2

I am currently developing a OpenGL application. So far everything worked well while programming the API.

For the usual datatypes I use structs. For instance:

struct vec3 {
 GLfloat x;
 GLfloat y;
 GLfloat z;
}

But now I considered to use the same datatypes as simple arrays, for instance

typedef GLfloat vec3[3];

I really like to handle the types as simple arrays since it is easier to access them and I can even use loops to modify their values (for instance in GLfloat matrix[16]) However what kind of annoys me is that C does not allow to return arrays, so I have to provide the storage for operations myself mat4_identity(mat4 output) With a structure I could easily say

mat4 m = mat4_identity() clean and nicely.

My question now is: Which one is better performance wise (of course when having many verticies for instance, I can only think of heavy struct pointer dereferences + acesses) and which one should I actually use in the end for my OpenGL API.

8
  • 2
    Have you considered struct vec3 { GLfloat vec3[3]; } ? Commented Mar 26, 2017 at 21:56
  • @chux Yes but this seems more like a odd hack/workaround for me. Ideal would be if I could use structs but access them like arrays (obviously when they all consist of variables with the same datatype). Unfortunately this doesn't work either because I heard of special allignment or packaging inside the struct. Commented Mar 26, 2017 at 22:00
  • struct vec3 { union { struct { float x, y, z; }; float a[3]; }; Commented Mar 26, 2017 at 22:06
  • @Joe You forgot a curly bracket :| Also sizeof(struct xyz) does not have to be equal to sizeof(array) so writes to the struct do not map to the array. Commented Mar 26, 2017 at 22:14
  • yes, i did forget one, but the principle is clear. there's no reason for the compiler to lay out a struct of only one type different from an array of the same type. the likelihood of this being an issue on any normal compiler is very, very, low. Commented Mar 26, 2017 at 22:18

1 Answer 1

4

If you are using C11, you can have the best of both worlds!

union vec3 {
        struct {
            float x, y, z;
        };
        float xyz[3];
};

Then you can access them either way:

printf("%f %f %f\n", vec.x, vec.y, vec.z);
printf("%f %f %f\n", vec.xyz[0], vec.xyz[1], vec.xyz[2]);

If you are not using C11, you can still do this, but the struct with the three components must be named:

union vec3 {
    struct {
        float x, y, z;
    } components;
    float xyz[3];
}

As for efficiency, arrays are guaranteed to be contiguous (there's no gap between elements) while structs are not, so it may be that a struct wastes more memory. But I doubt that's a problem considering the amount of memory modern computers have.

Also note that while arrays decay to pointers, structs are not guaranteed to do so. Unless the struct fits in a register (vec3 probably doesn't) you should pass pointers to it rather than passing it by value.

Sign up to request clarification or add additional context in comments.

3 Comments

Does it guarantee that for instance vec3.components.y == vec3.xyz[1] or will allignment destroy everything?
Pass by value can frequently be more efficient as the compiler can more easily prove that no aliasing occurs.
@MuradBabayev as I already commented on your question, alignment won't destroy anything because there is no reason for the compiler to add padding (alignment reqs. are never larger than the size of an object)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.