FUD
FUD

Reputation: 5184

C pointers strange behaviour in loop

For the following code compiled with gcc -Wall -pedantic -std=c99 -g bug.c I see following strange result

#include<stdio.h>
#include<stdlib.h>

typedef struct node_ {
  int key;
} node;

void
add (node** cur, node* n)
{
  if(*cur)
  {
    printf("%p %p\n", (void *)*cur, (void *)n);
    printf("%d %d\n", (*cur)->key, n->key);
  }
  *cur = n;
}

int
main()
{
  node* previous = 0;
  char k[] = {1, 2, 3};
  /* add(&previous, &(node){k[0]}); */
  /* add(&previous, &(node){k[1]}); */
  /* add(&previous, &(node){k[2]}); */
  /* puts(""); */
  for(int i=0; i<3; ++i)
    add(&previous, &(node){k[i]});
}

Results

% gcc --version
gcc (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2
% ./a.out
0x7fff756d60f0 0x7fff756d60f0
2 2
0x7fff756d60f0 0x7fff756d60f0
3 3

With unrolled loop i see a correct behviour

0x7ffdae8c72d0 0x7ffdae8c72e0
1 2
0x7ffdae8c72e0 0x7ffdae8c72f0
2 3

Upvotes: 1

Views: 53

Answers (1)

melpomene
melpomene

Reputation: 85877

for(int i=0; i<3; ++i)
    add(&previous, &(node){k[i]});

This is equivalent to:

for(int i=0; i<3; ++i) {
    node tmp = { k[i] };
    add(&previous, &tmp);
}

Each time through the loop, a temporary node struct is created, used, and destroyed again. After the first iteration, looking at *previous is an error because it points to a variable that no longer exists.

This situation is equivalent to returning the address of a local variable from a function. (Except there's no separate function; we just leave a local block. But the principle is the same: We retain a pointer to a local variable after leaving its scope and ending its lifetime.)

Upvotes: 4

Related Questions