1

I have the following code:

int** x;

// Add 4 int pointers to x - code ommitted

// Pop the first element
int* a = x[0];
memmove(&x[0], &x[1], sizeof(int*) * 3);
x = realloc(x, sizeof(int*) * 3);

// Some code that uses 'a' - ommitted

As per my understanding a is now pointing at the first location x points to. But that memory location now actually contains the data that was previously on x[1] due to the memmove.

Looking at how this code is used, it seems that a should actually point to the value that was previously on x[0]. My question is, how is it possible for a to contain that previous value if that memory location has been now replaced by what was in x[1]?

thameera
  • 9,168
  • 9
  • 37
  • 38
  • 1
    you mnde a copy of `X[0]` in `a` a points whereever X[0] used to point – Jasen Jan 11 '15 at 07:01
  • 2
    Your understanding (or your wording) is wrong. `a` points to whatever address was stored in `x[0]` That the value is shifted down one is unrelated to `a` and is irrelevant. There are *two* copies of that address; one in `a` and one in `x[0]` before the shift. After, there is one (in `a`). – WhozCraig Jan 11 '15 at 07:17
  • @WhozCraig Does `memmove(&x[0], &x[1], sizeof(int*) * 3);` looks good I think this will lead to undefined behavior since they are two different pointers and which never had memory of `sizeof(int *) * 3` it would have been `sizeof(int) * 3`? – Gopi Jan 11 '15 at 07:20
  • @WhozCraig Your comment (the way you explained it) actually answered by question. My understanding was wrong. If you put it as an answer, I can accept it. – thameera Jan 11 '15 at 07:21
  • This question came up when I saw the code for `lval_pop` function here: http://buildyourownlisp.com/chapter9_s_expressions – thameera Jan 11 '15 at 07:22
  • 1
    @Gopi Assuming the OP has validly setup `x` to point to four `int*` (such as `int **x = malloc(4 * sizeof(*x));`, that `memmove` is valid and well-defined. It is effectively the same as `memmove(x, x+1, sizeof(*x)*3);` (the syntax of which I prefer over the OP's, but that is a preference more than anything else). – WhozCraig Jan 11 '15 at 07:24
  • @Gopi `x` has the type `int**`. `*x` has the type `int*`, so `sizeof(*x) == sizeof(int*)`. – user253751 Jan 11 '15 at 08:16

1 Answers1

2

a is a variable on the stack to which you assigned the value of x[0] before you changed (by memmove) the value of x[0]. Hence, a will retain the value of x[0] and the array x will have the original x[1],x[2],x[3] stored at x[0],x[1],x[2]

So basically a acts as a local variable which is a copy of the data at x[0]. The said data is an integer pointer but could be anything else.

sleeping_dragon
  • 701
  • 1
  • 10
  • 27
  • Even though the pointer `a` is on the stack, the actual data it points to is in the heap, right? Doesn't this data get overwritten? – thameera Jan 11 '15 at 07:13
  • 1
    @thameera this answer is correct, and mine would only duplicate it, so if anything you can/should accept it. Regarding the actual data pointing to the heap, that is dependent on what you stored in `x[0]`. *None* of this *has* to be on the heap. `int ar[4]; int *x[4] = {ar,ar+1,ar+2,ar+3};` There, no heap, your code would still be valid against that `x`. – WhozCraig Jan 11 '15 at 07:27