Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do data member addresses lie between (this) and (this+1)?

Suppose that we have the following two inequalities inside a member function

this <=  (void *) &this->data_member

and

&this->data_member < (void *) (this+1) 

Are they guaranteed to be true? (They seem to be true in a few cases that I checked.)

Edit: I missed ampersands, now it's the correct form of inequalities.

like image 615
user10636819 Avatar asked Dec 10 '18 11:12

user10636819


2 Answers

From CPP standard draft 4713:

6.6.2 Object model [intro.object]/7
An object of trivially copyable or standard-layout type (6.7) shall occupy contiguous bytes of storage.

12.2 Class members [class.mem]/18
Non-static data members of a (non-union) class with the same access control (Clause 14) are allocated so that later members have higher addresses within a class object.

12.2 Class members [class.mem]/25
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class subobject (if any).

Taking all the above together, we can say the first equation holds for at least trivially copyable objects.

Also from the online cpp reference:

The result of comparing two pointers to objects (after conversions) is defined as follows:

1) If two pointers point to different elements of the same array, or to subobjects within different elements of the same array, the pointer to the element with the higher subscript compares greater. In other words, they results of comparing the pointers is the same as the result of comparing the indexes of the elements they point to.
2) If one pointer points to an element of an array, or to a subobject of the element of the array, and another pointer points one past the last element of the array, the latter pointer compares greater. Pointers to single objects are treated as pointers to arrays of one: &obj+1 compares greater than &obj (since C++17)

So if your data_member is not a pointer and has not been allocated memory separately, the equations you have posted hold good for at least trivially copyable objects.

like image 131
P.W Avatar answered Oct 19 '22 06:10

P.W


The full standard text amounts to this:

[expr.rel] - 4: The result of comparing unequal pointers to objects82 is defined in terms of a partial order consistent with the following rules:

We are dealing with a partial order here, not a total order. That does mean a < b and b < c implies a < c, but not much else.

(Note 82 states that non-array objects are considered elements of a single-element array for this purpose, with the intuitive meaning/behavior of "pointer to element one past the end").

(4.1) If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript is required to compare greater.

Pointers to different members are not pointers to (subobjects of) elements of the same array. This rule does not apply.

(4.2) If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member is required to compare greater provided the two members have the same access control ([class.access]), neither member is a subobject of zero size, and their class is not a union.

This rule only relates pointers to data members of the same object, not of a different object.

(4.3) Otherwise, neither pointer is required to compare greater than the other.

Thus, you do not get any guarantees from the standard. Whether you can find a real-world system where you get a different result than you expect is another question.

like image 42
Max Langhof Avatar answered Oct 19 '22 04:10

Max Langhof