Breaking it down line by line:
int **p = (int **)malloc(2 * sizeof(int *));
After this line executes, you have the following:
+---+ +---+
p: | | --------> [0]: | | ---?
+---+ +---+
[1]: | | ---?
+---+
?
indicates that p[0]
and p[1]
contain indeterminate pointer values (malloc
does not initialize the memory it allocates); these pointer value are most likely not valid (i.e., do not correspond to the address of an object in your program).
p[0] = (int *)malloc(2 * sizeof(int));
After this line executes, you have the following:
+---+ +---+ +---+
p: | | --------> [0]: | | ------> [0]: | ? |
+---+ +---+ +---+
[1]: | | ---? [1]: | ? |
+---+ +---+
Again, ?
represents an indeterminate value.
p[1] = p[0];
After this line executes, you have the following:
+---+ +---+ +---+
p: | | --------> [0]: | | ---+--> [0]: | ? |
+---+ +---+ | +---+
[1]: | | ---+ [1]: | ? |
+---+ +---+
Now, p[0]
and p[1]
are pointing to the same block of memory. Thus, p[0][0]
and p[1][0]
resolve to the same object. If we unroll your loop, we see the following sequence of assignments:
p[0][0] = 0 + 0;
+---+ +---+ +---+
p: | | --------> [0]: | | ---+--> [0]: | 0 |
+---+ +---+ | +---+
[1]: | | ---+ [1]: | ? |
+---+ +---+
p[0][1] = 0 + 1;
+---+ +---+ +---+
p: | | --------> [0]: | | ---+--> [0]: | 0 |
+---+ +---+ | +---+
[1]: | | ---+ [1]: | 1 |
+---+ +---+
p[1][0] = 1 + 0;
+---+ +---+ +---+
p: | | --------> [0]: | | ---+--> [0]: | 1 |
+---+ +---+ | +---+
[1]: | | ---+ [1]: | 1 |
+---+ +---+
p[1][1] = 1 + 1;
+---+ +---+ +---+
p: | | --------> [0]: | | ---+--> [0]: | 1 |
+---+ +---+ | +---+
[1]: | | ---+ [1]: | 2 |
+---+ +---+
This is why you're seeing the ouput you're seeing. The fact that p[0]
and p[1]
show the same value in your output should have been a big hint.
If p[1]
is meant to point to a different array from p[0]
, then you'll need to allocate another block of memory for p[1]
to point to:
p[1] = malloc( 2 * sizeof *p[1] );
As a matter of practice, you'll want to explicitly free
everything you allocate, even if your program is about to exit - it's just a good habit to get into:
free( p[0] ); // free each p[i] *before* freeing p
free( p[1] ); // assuming you added the malloc for p[1]
free( p );
If this is meant to be C code, lose the cast on the malloc
calls - it's unnecessary, it just adds visual clutter, and under C89 could mask a bug if you forgot to include stdlib.h
. A much better way to write those calls is
int **p = malloc( 2 * sizeof *p );
and
p[0] = malloc( 2 * sizeof *p[0] );
If this is meant to be C++ code, use new
and delete
instead of malloc
and free
.