3

Are class members in c++ guaranteed to be contiguous?

I've tried running the following code with almost all popular c++ compilers, and all of them yield the result 4, which is the relative address of the variable y. Is that a coincidence, or is it guaranteed by the language specifications to be this way? Isn't it possible that the compiler will not make the members x and y contiguous with the class basic address/ contiguous with each other?

Please note that this thread does not answer this question.

#include <iostream>

using namespace std;

class A {
public:

    void f(){
        cout << &(this->y) << endl;
    }

    int x, y;
};


int main(int argc, const char* argv[])
{
    A *a = 0;
    a->f();

    return 0;
}
sepp2k
  • 363,768
  • 54
  • 674
  • 675
DorHugi
  • 142
  • 10
  • It depends on structure member alignment. Try to place `char c` before `int x,y;` - you will be suprized. – Dmitry Sazonov Jan 17 '18 at 11:53
  • Possible duplicate of https://stackoverflow.com/questions/47592782/is-order-of-members-in-memory-guarantted-for-class-private-members-in-c – StoryTeller - Unslander Monica Jan 17 '18 at 11:54
  • 1
    It's complicated the standard makes some requirements but allows a lot of latitude as well. Start here (the rabbit hole is deep): http://en.cppreference.com/w/cpp/language/object and here: http://en.cppreference.com/w/cpp/language/memory_model – Richard Critten Jan 17 '18 at 11:55
  • 2
    @RichardCritten: More of a rabbit warren, or even an entire leporine ecosystem, than a hole. – Bathsheba Jan 17 '18 at 11:55
  • 1
    @Bathsheba how about: _"You Are In a Maze of Twisty Little Passages, All Alike"_ – Richard Critten Jan 17 '18 at 11:59
  • @RichardCritten: Or this place; the books are optional: https://en.wikipedia.org/wiki/The_Library_of_Babel – Bathsheba Jan 17 '18 at 12:00
  • 1
    Dereferencing a null pointer is Undefined Behavior. Never mind the gap between `x` and `y`, even if `A` had no data members and even if `A::f` would be empty this would still be UB. You cannot conclusively say that "all compilers return 4, the offset of y". – MSalters Jan 17 '18 at 12:00
  • Thanks for all the great comments. – DorHugi Jan 17 '18 at 12:02
  • Can you elaborate on why the linked thread does not answer your question? – AndyG Jan 17 '18 at 12:25
  • Also note that even if they *are* contiguous, you are not allowed to try to access them all by incrementing a pointer. That would violate other rules. – Bo Persson Jan 17 '18 at 12:46
  • @AndyG No one had given a definite answer in the linked post, and the answers focused on alternatives to initializing multiple class members, and the corresponding coding conventions. My question is more theoretical, since relaying on variables location in memory is obviously bad coding. – DorHugi Jan 17 '18 at 13:02

1 Answers1

6

Because your class is not a polymorphic type, has no base class, and all the members are public, the address of x is guaranteed to be the address of the class.

Also, the address of y is guaranteed to be after the address of x, although there could be an arbitrary amount of padding between them. So yes, your result is a coincidence.

If your class is polymorphic, i.e. has a virtual function somewhere in either it or a base class, or the members are protected or private, then all bets are off.

So in your case, (void*)&(this->x) is (void*)this, and the address of this->y must be higher than the address of this->x.

Finally if you need the class members to be contiguous, and mutually reachable by pointer arithmetic, use

int x[2];

instead as the member.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • The c++ standard [\[class.mem/17\]](https://timsong-cpp.github.io/cppwp/n4659/class.mem#17): "Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other;" so I am wondering if for standard layout struct this sentence could not be interpreted as: "If the alignment is adequate, there should not be space between 2 non static data members"? (a literal translation of the standard sentence in my native language would naturaly imply it) Is it the case in english? – Oliv Jan 17 '18 at 12:32
  • 2
    @Oliv: "Might cause" is the key here: because of this you need to assume that it will happen, otherwise you are not writing portable C++. – Bathsheba Jan 17 '18 at 12:39
  • @Oliv: I don't think the standard makes any guarantees about padding between members in a standard layout struct, only that there's no padding at the beginning. – AndyG Jan 17 '18 at 12:40
  • @AndyG This is realy strange why calling them standard layout if the standard does not define their layout. I thought that standard layout struct existed in order to allow communication between different executable. Nevertheless if their layout is not standardized, so theirlayout is uniquely specified by each compiler, which is the case for non standard layout struct, which make this concept absolutely point less! – Oliv Jan 17 '18 at 13:09
  • @Bathsheba For what purpose are standard layout struct sufficiently well specified? I actualy have never found out any application of this standard concept. – Oliv Jan 17 '18 at 13:12
  • @Oliv: Compatibility with C, for one. – Bathsheba Jan 17 '18 at 13:13
  • 2
    @Bathsheba I think that the specification of standard layout struct is necessary for compatibility with C, but it is not sufficient. A compiler could add more padding in C++ than in C for example. – Oliv Jan 17 '18 at 13:22