Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of storage inside 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 standard specifies any order of storage among -

  1. The elements inside a C structure.
  2. Data members inside an object of a C++ class.
like image 387
Amit Tomar Avatar asked Jul 05 '12 07:07

Amit Tomar


People also ask

How are structures stored in memory?

Struct members are stored in the order they are declared. (This is required by the C99 standard, as mentioned here earlier.) If necessary, padding is added between struct members, to ensure that the latter one uses the correct alignment. Each primitive type T requires an alignment of sizeof(T) bytes.

Does order matter in struct?

The order of fields in a struct does matter - the compiler is not allowed to reorder fields, so the size of the struct may change as the result of adding some padding.

Are structs stored on the stack C?

So, while instances of a class are stored in the heap, instances of a struct are stored in the stack.

What is structure in structure?

A nested structure in C is a structure within structure. One structure can be declared inside another structure in the same way structure members are declared inside a structure.


3 Answers

C99 and C++ differ a bit on this.

The C99 standard guarantees that the fields of a struct will be laid out in memory in the order they are declared, and that the fields of two identical structs 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 specified to be zero, but the offsets after that are not specified by the standard. This is to allow C compilers to adjust the offsets of each field so the field will satisfy any memory alignment requirements of the architecture. Because 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 treated like this. The standard gives the C++ compiler quite a bit of freedom in how it organizes a class when the class uses multiple inheritance, has non-public fields or members, or contains virtual members.

What this means for your examples:

dataType1 firstMemberInsideStruct = (dataType1)(*instance2);

This line is okay only if dataType1, dataType2, and dataType3 are plain old data. If any of them are not, then the customType struct 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 are POD, because the CustomType class has private instance variables. This makes it not a POD class, and so you cannot assume that its first instance variable will be ordered in a particular way.

like image 132
sfstewman Avatar answered Sep 30 '22 13:09

sfstewman


9.0.7

A standard-layout class is a class that: — has no non-static data members of type non-standard-layout class (or array of such types) or reference, — has no virtual functions (10.3) and no virtual base classes (10.1), — has the same access control (Clause 11) for all non-static data members, — has no non-standard-layout base classes, — either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and — has no base classes of the same type as the first non-static data member.108

9.2.14

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

9.2.20

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [ Note: There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment. — end note ]

like image 39
ForEveR Avatar answered Sep 30 '22 14:09

ForEveR


It's not always safe to do so. If the classes have virtual methods, it most definitely is not. Data members are guaranteed to appear in the same order for the same access level chunk, but these groups can be reordered.

In order to be safe with these type of casts, you should provide a conversion constructor or a cast operator, and not rely on implementation details.

like image 24
Luchian Grigore Avatar answered Sep 30 '22 14:09

Luchian Grigore