1
struct XYZ {
    XYZ *adress;
};

XYZ *Ex;
int main() {
    Ex = new XYZ[3];
    Ex->adress = (++Ex);
    cout << Ex->adress << endl;
    Ex->adress = (++Ex);
    cout << Ex->adress << endl;
    Ex->adress = (--Ex)->adress;
    cout << Ex->adress << endl;    

Output:

0105E424        
0105E428
0105E424
struct XYZ {
    XYZ *adress;
};

XYZ *Ex;

void copy_adress(XYZ *Ex) {
    Ex->adress = (++Ex);
}

int main() {
    Ex = new XYZ[3];
    copy_adress(Ex);
    cout << Ex->adress << endl;
    Ex->adress = (++Ex);
    cout << Ex->adress << endl;
    Ex->adress = (--Ex)->adress;
    cout << Ex->adress << endl;

Output:

CDCDCDCD
00A3E53C
CDCDCDCD

Can you tell me why this is happening, and how I can fix it?

5
  • On visual studio in debug mode the pattern CDCDCDCD means uninitialized heap memory. https://stackoverflow.com/a/127404/487892 Commented May 5, 2020 at 0:04
  • 1
    Probably what happens: Ex points to an array. When copy_adress is called, the parameter Ex ends up incremented before it is evaluated in the expression Ex->adress, causing the address to be stored in the field of the second array element. Upon returning to main, the global Ex still points to the first array element (it was not incremented), so the value of Ex->adress is uninitialized (the compiler set it to the distinctive 0xCDCDCDCD pattern). However, since the behavior is undefined, this is just conjecture. Commented May 5, 2020 at 0:08
  • @JaMiT Isn't this fine in c++17? Commented May 5, 2020 at 0:08
  • 1
    @cigien Did that change make it in? Honestly, I haven't really kept up with this aspect of the language because I avoid these kinds of expressions for style reasons / code readability. (I did finally find that C++17 note at the end of the duplicate, but that was mentioned as a proposal, which sounds like it was not definitely in when that was written.) Commented May 5, 2020 at 0:13
  • @JaMiT I'm not 100% sure (I rarely am), but I'm pretty sure this is ok now. Definitely not code that should be written :) anyway, I voted to reopen the question. Commented May 5, 2020 at 0:15

2 Answers 2

4

Pointers behave just like regular objects when you copy them, or pass them to a function. Changes to the copy are not reflected in the original. To make the changes in a function visible, you need to take it by reference:

void copy_adress(XYZ *&Ex) {
   Ex->adress = (++Ex);
}

Now, the 2 versions are equivalent.

Sign up to request clarification or add additional context in comments.

2 Comments

It works only if the reference is there.
It would also avoid confusion to use a different name for the function parameter than the global variable
1

(This is supplemental information, cigien answered the main question)

There was some speculation in comments about the sequencing of Ex->adress = (++Ex). Since C++17, the right operand of = is sequenced-before the left operand. And since C++11 both operands are sequenced-before the assignment.

So ++Ex is completed, and then the new value of Ex is used for the computation Ex->address. Prior to C++17 this was undefined behaviour.

The second code example does have UB but for a different reason: reading uninitialized memory:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.