简体   繁体   中英

Understanding memory allocation for a 2D like array

I'm trying to understand what is happening when the code is printed.

I know that p[0] and p[1] are pointing to the same thing and if p[1] had it's own malloc, p[0][0] would result in 0 but it's resulting in 1.

I'm trying to understand what is causing it to result in 1. So the result of this code is:

1
2
1
2 

But I'm not sure how.

The code:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int i,j;
    int **p = (int **)malloc(2 * sizeof(int *));
    p[0] = (int *)malloc(2 * sizeof(int));
    p[1] = p[0];
    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            p[i][j] = i + j;
    printf("%d\n",p[0][0]);
    printf("%d\n",p[0][1]);
    printf("%d\n",p[1][0]);
    printf("%d\n",p[1][1]);
    return 0;
}

Let q be the result of the malloc in p[0] = (int *)malloc(2 * sizeof(int)); .

Then, after that assignment and p[1] = p[0]; , both p[0] and p[1] are q .

Then the statement p[i][j] = i + j; is equivalent to q[j] = i+j; , regardless of whether i is 0 or 1.

Then these loops:

    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            p[i][j] = i + j;

perform two assignments when i is 0:

q[0] = 0 + 0;
q[1] = 0 + 1;

and two assignments when i is 1:

q[0] = 1 + 0;
q[1] = 1 + 1;

The latter two overwrite the first two, so the result is q[0] contains 1 and q[1] contains 2.

Then this code:

    printf("%d\n",p[0][0]);
    printf("%d\n",p[0][1]);
    printf("%d\n",p[1][0]);
    printf("%d\n",p[1][1]);

is equivalent to:

    printf("%d\n",q[0]);
    printf("%d\n",q[1]);
    printf("%d\n",q[0]);
    printf("%d\n",q[1]);

so it prints 1, 2, 1, and 2.

Both values are set twice , once through p[0][j] and the second time through p[1][j] . Since second time i is 1, the values put into those cells are 1 + j .

Code explained with comments:

// allocating space for 2 pointers to int
// this emulates an array of pointers to int *p[2]
int **p = malloc(2 * sizeof(int *)); 

// allocating space for the first pointer, which will contain 2 ints
p[0] = malloc(2 * sizeof(int));  

// assigning the pointer p[0] or p + 0 to the pointer p[1] or p + 1
// both pointer are now pointing to the same memory location as you already established
// so there is no need to allocate memory for p[1] as it's already 
// pointing to a valid memory location
p[1] = p[0]; 

// assigning the values, there is a redundancy here the values are assigned twice 
// albeit different, 0 1 in the first iteration and rewritten in the second 1 2
for (i = 0; i < 2; i++)
    for (j = 0; j < 2; j++)    
        p[i][j] = i + j;

// the same result  could be achieved, with half of the iterations
// as both pointers point to the same location
for (i = 1; i < 2; i++) //i = 1
    for (j = 0; j < 2; j++)    
        p[i][j] = i + j;

// printing the values, note that these are the same values from the same location
// but retrieved with different pointers p[0] and p[1]
printf("%d\n", p[0][0]);
printf("%d\n", p[0][1]);
printf("%d\n", p[1][0]);
printf("%d\n", p[1][1]);

I should also note that casting malloc return is not necessary.

The pointer p[1] is set to the value of the pointer p[0]

p[1] = p[0];

So the both pointers point to the same array with two elements due to this dynamic memory allocation

p[0] = (int *)malloc(2 * sizeof(int));

The outer for loop in these loops

for(i = 0; i < 2; i++)
    for(j = 0; j < 2; j++)
        p[i][j] = i + j;

at first uses the pointer p[0] and then the pointer p[1] that points to the same array. So the first iteration of the outer loop can be entirely ignored because in the second iteration of the outer loop the pointed array is overwritten using the pointer p[1] . So the loops can be rewritten using only one loop

    for( j = 0; j < 2; j++)
        p[1][j] = 1 + j;

Thus p[1][0] is set to 1 + 0 that is to 1 (in the first iteration of the loop) and p[1][1] is set to 1 + 1 that is to 2 (in the second iteration of the loop)

In these calls of printf the same array is outputted two times using the pointers p[0] and p[1] that point to the same array.

printf("%d\n",p[0][0]);
printf("%d\n",p[0][1]);
printf("%d\n",p[1][0]);
printf("%d\n",p[1][1]);

These calls are equivalent to calls either like

printf("%d\n",p[0][0]);
printf("%d\n",p[0][1]);
printf("%d\n",p[0][0]);
printf("%d\n",p[0][1]);

or like

printf("%d\n",p[1][0]);
printf("%d\n",p[1][1]);
printf("%d\n",p[1][0]);
printf("%d\n",p[1][1]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM