Storage order within a structure / object

Consider these two cases:

struct customType { dataType1 var1; dataType2 var2; dataType3 var3; } ; customType instance1; // Assume var1, var2 and var3 were initialized to some valid values. customType * instance2 = &instance1; dataType1 firstMemberInsideStruct = (dataType1)(*instance2); 



 class CustomType { public: dataType1 member1; dataType2 member2; retrunType1 memberFunction1(); private: dataType3 member3; dataType4 member4; retrunType2 memberFunction2(); }; customType object; // Assume member1, member2, member3 and member4 were initialized to some valid values. customType *pointerToAnObject = &object ; dataType1 firstMemberInTheObject = (dataType1) (*pointerToAnObject); 

Is it always safe to do this?

I want to know if the standard indicates any storage order among -

  • Elements inside structure C.
  • Data elements inside a C ++ class object.
+3
c ++ c pointers class structure
Jul 05 2018-12-12T00:
source share
4 answers

C99 and C ++ are slightly different from this.

The C99 standard ensures that structure fields will be laid out in memory in the order in which they are declared, and that the fields of two identical structures will have the same offsets. See this question for the relevant sections of the C99 standard. To summarize: the offset of the first field is indicated to be zero, but the offsets after that are not defined by the standard. This allows C compilers to adjust the offsets of each field so that the field satisfies any memory alignment requirements in the architecture. Since this is implementation dependent, C provides a standard way to determine the offset of each field using the offsetof macro.

C ++ offers this guarantee only for Plain Old Data (POD) . C ++ classes that are not plain old data cannot be viewed like this. The standard gives the C ++ compiler quite a bit of freedom in how it organizes the class when the class uses multiple inheritance, has non-public fields or members, or contains virtual members.

What does this mean for your examples:

 dataType1 firstMemberInsideStruct = (dataType1)(*instance2); 

This line is fine only if dataType1, dataType2 and dataType3 are regular old data. If any of them is not present, then the customType structure may not have a trivial constructor (or destructor), and this assumption may not hold.

 dataType1 firstMemberInTheObject = (dataType1) (*pointerToAnObject); 

This line is not safe regardless of whether dataType1 , dataType2 and dataType3 , because the CustomType class has private instance variables. This makes it not a POD class, so you cannot assume that its first instance variable will be ordered in a certain way.

+4
Jul 05 '12 at 8:28
source share

9.0.7

A standard layout class is a class that: - has no non-static data, members of a non-standard layout type (or an array of such types) or a link, - does not have virtual functions (10.3) and a virtual base classes (10.1), - has the same access control ( clause 11) for all non-static data elements, - does not have base classes of non-standard layout, - either does not have non-static data members in the derived class itself, and in the most basic class with non-static data elements or does not have the base classes with non-static data elements, and - does not them a base class of the same type as the first data item nonstatic .108

9.2.14

Non-static data members of a (non-unitary) class with the same access (section 11) are allocated so that later members have higher addresses inside the class object. The distribution order of non-static data members with different access control is not defined (11). Implementation alignment requirements can cause two neighboring members not to stand out immediately after each other; so the space requirements for managing virtual functions (10.3) and virtual base classes (10.1).

9.2.20

A pointer to an object of the standard layout structure, converted accordingly using reinterpret_cast, points to its initial member (or if this member is a bit field, then to the block in which it is located) and vice versa. [Note. Thus, in a standard structural object, but not at its beginning, as necessary to achieve appropriate alignment. - final note]

+6
Jul 05 '12 at 8:01
source share

It is not always safe. If classes have virtual methods, this is definitely not the case. Data items are guaranteed to be displayed in the same order for the same access level, but these groups can be reordered.

To be safe with these types of throws, you must provide a transform constructor or translation operator, rather than relying on implementation details.

+1
Jul 05 2018-12-12T00:
source share

Typically, members of a C structure are stored in the order in which they are declared. However, the elements must be aligned correctly. Wikipedia has a good example of how this works .

I will repeat the iteration here:

If you have the following structure

 struct MixedData { char Data1; short Data2; int Data3; char Data4; }; 

padding will be inserted between different data types to ensure proper byte alignment. char aligned by 1 byte, short aligned by 2 bytes, int aligned by 4 bytes, etc.

Thus, to align Data2 2 bytes, a 1-byte padding between Data1 and Data2 will be added.

It is also worth noting that there are mechanisms that can change the alignment of the package. See # pragma pack .

0
Jul 05 2018-12-12T00:
source share



All Articles