1

I ran into this code:

#include <stdio.h>

void foo(int* p1, int* p2) 
{
   p1 = p2;
   *p1 = *p2 + 1; 
}

void bar(int** p1, int** p2) 
{
  p1 = p2;
  *p1 = *p2 + 1;
  **p1 = **p2 + 2;
}

void main (void) 
{
  int n[] = {1,2,3};
  int m[] = {4,5,6};
  int *p1 = n;
  int *p2 = m;

  foo(p1,p2);
  bar(&p1,&p2);
  printf("%d %d\n",*p1,*p2);
}

I thought the output will be [1,5] while it's [1,7]. Can someone explain the reason?

Thanks a lot

2501
  • 24,549
  • 4
  • 42
  • 83
  • 1
    Please post the code as a text in the Question body, not as a link. – SurvivalMachine Jul 02 '16 at 07:42
  • `void main(void)` has undefined behaviour in C standard, unless it is an implementation-defined way of prototyping `main`. See also http://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c – Antti Haapala Jul 02 '16 at 08:03
  • I updated the code. my question was about the pointer's behaviour. – Elad Pardilov Jul 02 '16 at 08:12
  • @EladPardilov Antti's comment is not relevant for this question. I rollbacked the question. If your implementation defines void main(void) as main, then that is correct. – 2501 Jul 02 '16 at 09:56

1 Answers1

3

At first, you need to distinguish p1 and p2 within main and p1, p2 within the functions, which are not the same. So I will rename the parameters of foo and bar into fp1, fp2, bp1, fp2 to be able to differentiate more clearly. This won't change anything in behaviour.

So main first calls foo(p1, p2);. fp1 and fp2 then are copies of the pointers p1 and p2. Within foo:

  1. fp1 = fp2; fp2 is assigned to fp1. So both fp1 and fp2 hold the address of the array p2 was assigned to (i. e. m within main).
  2. *p1 = *p2 + 1; as both p1 and p2 hold the address of m (or m[0], which is the same for arrays), m[0] is incremented (was 4, now is 5).

Then calling bar(&p1, &p2);. So bp1 and bp2 now hold the addresses of the two pointers p1 and p2 within main (i. e. you can modify p1 and p2 themselves from within bar!), which is going to happen then, too:

  1. bp1 = bp2; again both pointers hold the same address, which is the one of p2 within main (still with address of m[0]).
  2. *bp1 = *bp2 + 1; as both bp1 and bp2 point to the same pointer, results in incrementing this pointer, so effectively increments p2, now pointing to m[1].
  3. **bp1 = **bp2 + 2; bp1 and bp2 both point to p2, which points to m[1]. So m[1] is incremented by 2 (m[1] was 5, now is 7!).

Finally printing the values. Remember, p2 itself was modified within bar, now pointing to m[1], which again was modified to 7, so the result you did not expect...

Aconcagua
  • 19,952
  • 4
  • 31
  • 51