Location of data in the class

Started by
17 comments, last by frob 9 years, 10 months ago

when I define a class with only these variables


float _m11, _m12, _m13;
float _m21, _m22, _m23;
float _m31, _m32, _m33;

is it safe to assume that to access _m13 from the pointer of _m11 I can


(&_m11)[2]

and

to get to _m21


(&_m11)[3]

to my understanding this should be allowed, but I was wondering if it'll always be placed in RAM like this or some systems might shuffle them for a reason I don't know.

Advertisement

I was also curious if the same could be said for functions arguments,


Vector4(float _x, float _y, float _z, float _w);

Would all these be in the same order and sequential?

Thank you for any help, it would be much appreciated.

It's not safe because the compiler is allowed to add padding between the data members.

As mentioned above, it is not safe due to possible padding between members. You can however use a nameless struct here to achieve the same effect,


class matrix {
public:
 
   union {
        float m[9];
      struct {
         float _m11, _m12, _m13;
         float _m21, _m22, _m23;
         float _m31, _m32, _m33;
      };
   };
 
// now m[1] = _m11, m[2] = _m12 etc.
};

It is important to note that nameless structures are not standard although a few modern compilers support it.

I've seen this used before in a graphics rendering library.

The compiler does not reorder any members, and I assume there would be no padding, because 32-bit floats align correctly in 32-bit and 64-bit addressable memory, but it's not written in stone - the compiler is allowed to add padding if it wants to.

"I would try to find halo source code by bungie best fps engine ever created, u see why call of duty loses speed due to its detail." -- GettingNifty

Not what I wanted to hear, but thank you anyway :3

there's no way to ensure no padding is there?

guess it's back to my float _m[3][3] then

The compiler does not reorder any members, and I assume there would be no padding, because 32-bit floats align correctly in 32-bit and 64-bit addressable memory, but it's not written in stone - the compiler is allowed to add padding if it wants to.


I think assuming that is not unhealthy. I'm not in the habit of hand-rolling my matrix libraries but I would probably assume no padding and then
static_assert(sizeof(matrix) == 9 * sizeof(float), "This platform does not deal well with padding; must be handled explicitely");

Not what I wanted to hear, but thank you anyway :3

there's no way to ensure no padding is there?

guess it's back to my float _m[3][3] then

Technically you can enforce a specific alignment or none at all via compiler specific #pragma options. For example, in MSVC, #pragma pack directive or G++ attribute((packed)). TheComet is correct though, floats are very well standardized and guaranteed to be 32 bits so it is most probably safe to assume proper dword alignment without padding. The only guaranteed methods however would be compiler dependent; that is, resulting to nameless structures or #pragma.

You can also just overload operator[] and call it directly.

Alternatively just don't do it. You are not gaining anything from doing this after all. It can be done, of course, but at what benefit?

Not what I wanted to hear, but thank you anyway :3

there's no way to ensure no padding is there?

guess it's back to my float _m[3][3] then

Using these kind of trick, will work but it is also how you write unmaintainable code. And code readability is often more important than ease of writing your code, because in six months time you are going to be wondering why you wrote it that way.

The other way of doing this is


class Matrix44
{
private:
    union
    {
        float f[16];
        float mm[4][4];
        Vector4  v[4]; //Assuming vector4 is stored as 128 bytes contiguously
    } matrix;
}

You can now access matrix.f as an array, matrix.mm as a 2D array or as an array of vector4, if you add 16 float variables in the union you get 16 slot access options.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

Washu posted a very neat implementation here: http://www.gamedev.net/topic/391237-criticize-my-custom-vector-class/page-5#entry3598509

struct Vector3 {
  float x, y, z;
  
  float &operator[](int index) {
    assert(index >= 0 && index < 3);
    return this->*members[index];
  }

  float operator[](int index) const {
    assert(index >= 0 && index < 3);
    return this->*members[index];
  }

  static float Vector3::* const members[3];
};

float Vector3::* const Vector3::members[3] = { &Vector3::x, &Vector3::y, &Vector3::z};

This topic is closed to new replies.

Advertisement