nunojpg nunojpg - 11 months ago 71
C++ Question

Pointer arithmetic ignored by the compiler

I'm compiling the following with -O0 (recent gcc/clang) and they both give me a answer I don't expect.

#include <iostream>

struct xy{
int x,y;
};


int main()
{
xy a{1,2};

int x{1};
int y{2};

int *ptr1=&a.x;
int *ptr2=&x;

ptr1++; // I now point to a.y!
(*ptr1)++; // I now incremented a.y to 3

ptr2++; // I now point to y!
(*ptr2)++; // I now incremented y to 3

std::cout << "a.y=" << a.y << " ptr1=" << *ptr1 << '\n';
std::cout << "y= " << y << " ptr2=" << *ptr2 << '\n';
}


Output:

a.y=3 ptr1=3
y= 2 ptr2=2


So this access with pointers to non-class variables is being optimized-out by the compiler.

I also tried to mark the int and int* as volatile, but it didn't make any difference.

What part of the standard am I missing / why is the compiler allowed to do this?

Coliru snippet at: http://coliru.stacked-crooked.com/a/ed0757a6621c37a9

Answer Source

In the first case dealing with class members the part you are ignoring is the compiler is allowed to add any amount of padding in between members of a object and at the end of the object. Because of this increment a pointer to one member does not have to give you the next member.

The second part of the standard you are missing is it is illegal to access memory though a pointer to what it doesn't point to. Even though y might be there in memory the pointer is not allowed to access it. It is allowed to access x and it is allowed to compare to see if it one past x but it cannot dereference that one past x address.