-3

I would like help understanding this code:

void F (int a, int *b)
{
    a = 7 ;
    *b = a ;
    *b = 4 ;
    printf("%d, %d\n", a, *b);
    b = &a ;
}


int main()
{
    int m = 3, n = 5;
    F(m, &n) ;
    printf("%d, %d\n", m, n) ;
    return 0;
}

I am confused why this does not result in unexpected behavior. At the end of the function F, the value of b is 7. But when I return it is clear that nothing after ' b = &a ' impacts the value of n/b. I thought that pointing to a local variable would result in garbage/unexpected behavior when the scope changed, but that doesn't appear to be the case.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
JohnKraz
  • 119
  • 1
  • 1
  • 8
  • 1
    *I am confused why this does not result in unexpected behavior* - so you *expect* the *unexpected* behavior? Hm. I see a contradiction here... – Eugene Sh. Oct 24 '16 at 20:05
  • at the end of the function `F`, `b` equals the address of `a`, and `a` is local to the function `F`. – yano Oct 24 '16 at 20:06
  • 2
    So, what behaviour **did** you expect to be unexpected? Well, it results in _un**defined** behaviour_. Isn't that enough? How about reading the man-pages of functions you use? `%d` takes an `int` argument, not a pointer! – too honest for this site Oct 24 '16 at 20:07
  • C11 draft standard n1570: *6.5.2.2 Function calls 4 An argument may be an expression of any complete object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument. 93) A function may change the values of its parameters, but these changes cannot affect the values of the arguments. On the other hand, it is possible to pass a pointer to an object, and the function may change the value of the object pointed to.* – EOF Oct 24 '16 at 20:08
  • 1
    This is `c++`, but same concepts: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794 – yano Oct 24 '16 at 20:09
  • This is not a duplicate of the [famous question on the topic](http://stackoverflow.com/q/6441218/335858), because OP falls short of setting up undefined behavior. In fact, he wants to see why the thing that he does is *not* causing undefined behavior. Voting to re-open the question. – Sergey Kalinichenko Oct 24 '16 at 20:44

2 Answers2

2

When you call F, you pass the value of m and the address of n. In F, b is a pointer to n so that when you change the value of *b, the value of n is changed. However, in "b = &a;" you are changing where b points. After that line, b no longer points to n. Instead, it points to a. That line does nothing at all to the variable n back in main(). After that point, if you change the value of *b, you will change the value of *b and its alias, a. It will not change the value of n in main.

tjhighley
  • 188
  • 1
  • 7
  • Thanks for the quick reply. I was under the (erroneous) assumption that the parameter int *b was synonymous with n. – JohnKraz Oct 24 '16 at 20:09
  • *b "was" synonymous with n. The line "b = &a" changes the meaning of *b. After that, *b is synonymous with a. – tjhighley Oct 24 '16 at 20:11
  • Yeah, I think I overlooked that I was passing &n. For some reason I thought n was a pointer to an int as well. – JohnKraz Oct 24 '16 at 20:17
  • Incidentally, you may want to change the title of the question, if possible. This question isn't about pointing to a local variable after all. It's about changing the a pointer parameter so that it points to something else. – tjhighley Oct 24 '16 at 20:28
0

At the end of the function F, the value of b is 7

The value of b is not 7; b is set to point to a, which has the value of 7

But when I return it is clear that nothing after b = &a impacts the value of n

Although b is a pointer, it is passed by value. b inside F behaves as if it were a separate, fully independent, local variable. Any modifications to it made inside F are local to F.

In fact, you cannot trigger undefined behavior in main by actions inside F, because main is not receiving any pointers from F. If you want to make undefined behavior, pass a pointer to pointer into F, and assign it to point to a local variable:

void CauseUB(int a, int **b) {
    *b = &a;
}
int main() {
    int x = 5, *y = &x;
    printf("This is OK: %d\n", *y);
    CauseUB(x, &y); // Pointer to pointer
    printf("This is UB: %d\n", *y);
    return 0;
}

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523