Do class/struct members always get created in memory in the order they were declared?
C99 §6.7.2.1 clause 13 states:
Within a structure object, the
non-bit-field members and the units in
which bit-fields reside have addresses
that increase in the order in which
they are declared.
and goes on to say a bit more about padding and addresses. The C89 equivalent section is §6.5.2.1.
C++ is a bit more complicated. In the 1998 and 2003 standards, there is §9.2 clause 12 (clause 15 in C++11):
Nonstatic data members of a
(non-union) class declared without an
intervening access-specifier are
allocated so that later members have
higher addresses within a class
object. The order of allocation of
nonstatic data members separated by an
access-specifier is unspecified
(11.1). 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).
Does the order of members in a struct matter?
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.
In this case, however, you are defining a so-called flexible member, an array the size of which you can change. The rules for flexible members are that
- There may never be more than one such member,
- If present, the flexible member must be the last one in the
struct
, and - The
struct
must have at least one member in addition to the flexible one.
Take a look at this Q&A for a small illustration on using flexible structure members.
Order of fields in C/C++ structs
The general rules about field layout in C are:
- The address of the first member is the same as the address of the struct itself. That is, the
offsetof
of the member field is 0. - The addresses of the members always increase in declaration order. That is, the
offsetof
of the n-th field is lower than that of the (n+1)-th member.
In C++, of course, that is only true if it is a standard layout type, that is roughly, a class or struct with no public/private/protected mixed members, no virtual functions and no members inherited from other classes.
Member fields, order of construction
Yes, the order of construction is always guaranteed. It is not, however, guaranteed to be the same as the order in which the objects appear in the initializer list.
Member variables are constructed in the order in which they are declared in the body of the class. For example:
struct A { };
struct B { };
struct S {
A a;
B b;
S() : b(), a() { }
};
a
is constructed first, then b
. The order in which member variables appear in the initializer list is irrelevant.
Can we scramble the declaration order in C or C++?
Run-time foxing is the best way, then you only have to release a single version. Where a struct
has several fields of the same type, you can use an array instead. Step 1. Instead of a structure with three int
fields use an array
#define foo 0
#define bar 1
#define zee 2
struct abc {
int scramble [3];
};
...
value = abc.scramble[bar];
Step 2, now use an indexing array which is randomised every time the program is run.
int abcindex [3]; // index lookup
int abcpool [3]; // index pool for randomise
for (i=0; i<3; i++) // initialise index pool
abcpool[i] = i;
srand (time(NULL));
for (i=0; i<3; i++) { // initialise lookup array
j = rand()%(3-i);
abcindex[i] = abcpool[j]; // allocate random index from pool
abcpool[j] = abcpool[2-i]; // remove index from pool
}
value = abc.scramble[abcindex[bar]];
Another way to try to fox a hacker is to include subterfuge variables that behave as if they have something to do with it but make the program exit if tampered with. Lastly you can keep some kind of checksum or encrypted copy of key variables, to check if they have been tampered with.
Members declaration order in a class if they depend on eachother, optimal solution
As the order of initialisation is dependent on the order they are defined in your class, the member order is ignored: C++: Initialization Order of Class Data Members.
So I would just move the integer and string above MyOb1
and MyOb2
, also @Matt McNabb also pointed out that you should use the params passed in your constructor in the initialisation of your MyOb1/2 objects to avoid ambiguity (a sensible suggestion):
class MyClass
{
private:
int i;
std::string str;
MyOb1 Obj1;
MyOb2 Obj2;
public:
MyClass(int iIn, const std::string& strIn)
: i(iIn), // here
str(strIn),
Obj1(iIn),
Obj2(iIn, strIn) {}
}
To quote from the standard section 12.6.2 (the latest draft has this on page 266):
5 Initialization shall proceed in the following order:
— First, and only for the constructor of the most derived class as
described below, virtual base classes shall be initialized in the
order they appear on a depth-first left-to-right traversal of the
directed acyclic graph of base classes, where “left-to-right” is the
order of appearance of the base class names in the derived class
base-specifier-list.— Then, direct base classes shall be initialized in declaration order
as they appear in the base-specifier-list (regardless of the order of
the mem-initializers).— Then, nonstatic data members shall be initialized in the order they
were declared in the class definition (again regardless of the order
of the mem-initializers).— Finally, the body of the constructor is executed. [Note: the
declaration order is mandated to ensure that base and member
subobjects are destroyed in the reverse order of initialization. ]
Related Topics
Which Headers in the C++ Standard Library Are Guaranteed to Include Another Header
Is There a Formula to Determine Overall Color Given Bgr Values? (Opencv and C++)
Std::Shared_Ptr Thread Safety Explained
Iterating C++ Vector from the End to the Beginning
Why C++ Copy Constructor Must Use Const Object
Measure Execution Time in C++ Openmp Code
Vector Push_Back Calling Copy_Constructor More Than Once
Good Tools for Creating a C/C++ Parser/Analyzer
How to Emit Cross-Thread Signal in Qt
Should I Worry About the Alignment During Pointer Casting
Is There Any Guarantee of Alignment of Address Return by C++'s New Operation
Why Do Compilers Allow String Literals Not to Be Const
Convert Between String, U16String & U32String
Is It Safe to Push_Back an Element from the Same Vector
Why Can't a Derived Class Call Protected Member Function in This Code
Practical Use of Zero-Length Bitfields
What's the Behavior of an Uninitialized Variable Used as Its Own Initializer
Temporary Objects - When Are They Created, How to Recognise Them in Code