zeroes00
zeroes00

Reputation: 531

The order of data in memory

A few simple questions.

const int gFirst;
const int gSecond;

struct Data
{
    static int First;
    static int Second;

    int first;
    int second;
};

Data data;

Is it guaranteed that the following statements are true?

  1. &gFirst < &gSecond
  2. &Data::First < &Data::Second
  3. &data.first < &data.second

Upvotes: 5

Views: 214

Answers (2)

Loki Astari
Loki Astari

Reputation: 264461

The answer:

1) Not guaranteed.
   But probably.
   But the order of initialization is guaranteed.
2) No. 
   You just have the declaration here.  
   You need to to define the instances in a source file.
   Then they will behave the same way as the objects in (1).
3) Yes.

Upvotes: 6

GManNickG
GManNickG

Reputation: 503923

1) This result is unspecified.
2) This result is unspecified.*
3) Yes.

The relevant section in the standard is §5.9/2. Relational comparisons between the pointers p and q are only specified when:

  • p and q point to the same object or function, point to one past the end of the same array, or both are null. In this case, p <= q and p >= q are true, and p < q and p > q are false.
  • p and q point to nonstatic data members of the same object, the pointer to the later declared member compares greater. (Note, this comparison cannot be between access specifiers.)
  • p and q point to elements within the same array or one past the end of the array, the pointer to the element with the higher subscript or to one past the end of the array compares greater.
  • p and q point to data members of the same union object, in which case they compare equal.

In all other cases, the result is not specified.

*Because they are static, they (obviously) do not get the "nonstatic member" rules. They will be defined in some translation unit, and therefore are just like any other pointer. (Unspecified.)


Note! There is a way to get total ordering, and that is via std::less<void*> (and all the other comparative function objects.)

This is in §20.3.3/8:

For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

So while you don't know if std::less<void*>(&gFirst, &gSecond) is true or false, you are guaranteed:

std::less<void*>(&gFirst, &gSecond) ==
    std::greater<void*>(&gSecond, &gFirst);
std::less<void*>(&Data::First, &Data::Second) ==
    std::greater<void*>(&Data::Second, &Data::First);

Which can prove useful.

Upvotes: 8

Related Questions