1

Maybe the new code can explain what I mean.

#include <stdio.h>
#include <stdlib.h>
int main(void){
    int i_size = 2, j_size = 5, k_size = 5, l_size = 6, m_size = 6;
    int i = 0, j = 0, k = 0, l = 0, m = 0; 
    printf("ptr1\n");
    int** ptr1 = (int**) malloc(sizeof(int*) * i_size);
    for(i = 0; i < i_size; i++){
        printf("%d\n", ptr1 + i);
    }
    printf("ptr2\n");
    int** ptr2 =  (int**) malloc(sizeof(int*) * j_size);
    for(j = 0; j < j_size; j++){
        printf("%d\n", ptr2 + j);
    }
    printf("ptr3\n");
    int** ptr3 =  (int**) malloc(sizeof(int*) * k_size);
    for(k = 0; k < k_size; k++){
        printf("%d\n", ptr3 + k);
    }
    printf("ptr4\n");
    int** ptr4 =  (int**) malloc(sizeof(int*) * l_size);
    for(l = 0; l < l_size; l++){
        printf("%d\n", ptr4 + l);
    }
    printf("ptr5\n");
    int** ptr5 =  (int**) malloc(sizeof(int*) * m_size);
    for(m = 0; m < m_size; m++){
         printf("%d\n", ptr5 + m);
    }
    free(ptr1);
    free(ptr2);
    free(ptr3);
    free(ptr4);
    free(ptr5); 
    return 0;
}

The result is as below:

Result

It is funny that it seems for malloc function, the minimun size of array is 32 bytes. And the OS seems to preserve 8 bytes space because when I found that for l_size, it has 64 bytes. It means that if you want to malloc a 48-byte array, the OS will allocate more than 48-byte space.

update above

=====

My code is shown as below:

#include <stdio.h>
#include <stdlib.h>
int main(void){
    int i_size = 5, j_size = 6, i = 0, j = 0; 
    printf("Addresses of two dimensional pointer\n");
    int** ptr = (int**) malloc(sizeof(int*) * i_size);
    printf("%d:\t%d\n", &ptr, ptr);
    for(i = 0; i < i_size; i++){
        *(ptr + i) = (int*) malloc(sizeof(int) * j_size);
    }
    for(i = 0; i < i_size; i++){
        for(j = 0; j < j_size; j++){
            *(*(ptr+i) + j) = i * 2 + j;
        }
    }
    for(i = 0; i < i_size; i++){
        printf("%d:\t%d\n", ptr + i, *(ptr + i));
    }
    printf("==\n");
    for(i = 0; i < i_size; i++){
        for(j = 0; j < j_size; j++){
            printf("%d:\t%d\t%d\n",*(ptr + i) + j, *(*(ptr + i) + j), ptr[i][j]);
        }
        printf("==\n");
    }
    for(i = 0; i < i_size; i++){
        free(*(ptr + i));
    } 
    free(ptr);

    return 0; 
}

And the result as the folloing picture shows:

enter image description here

The code is running on the windows 10, 64-bit and compiled with TDM-GCC4.9.2 of Dev C++.

I am confused by the red block. Why is always 8 more bytes than the size of array. If I change the value of i_size to 6, it seems that the OS will give 64 bytes to ptr but not 48.

The result of changing the value of i_size to 6

I expect that the value 12021664 should be 12021648. If I change the value of i_size to 7, it is ok: the result of changing the value of i_size to 7

But when the value of i_size is 8, I expect the value 10710960 should be 10710944. But it doesn't work.

the result of changing the value of i_size to 8

smielqf
  • 13
  • 5

1 Answers1

3

ptr points to an array of int *. On your system, it appears that pointers are 8 bytes in size, so each member of the array is 8 bytes.

When you then print the address of each member as ptr + i, you see that they each differ by 8.

Also, you should be using %p to print pointers instead of %d. Using the wrong format specifier invokes undefined behavior.

Regarding the specific memory addresses returned by malloc, those are an implementation detail of the library. There is no requirement that successive allocations should be adjacent in memory. In fact, it makes sense that they are not adjacent because there is likely some metadata being stored in those in-between addresses which is being used internally by malloc.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Well, I think `%d` is not the key to the problem. I jus want to calculate the offset directly without converting hex number to decimal number, since the value of address is an integer. And I know the address is 8-byte long. But when I change the value of `i_size` to 6, why does the OS give 64 bytes to `ptr` but not 48. – smielqf Dec 07 '18 at 16:11
  • 2
    @smielqf no, the `%d` is not the actual problem, but using `%d` instead of `%p` is still wrong. You are just lucky that you get something more or less usefull with`%d`. Addresses on your platform are 64 bits and `int`s may be 32 bit values on your platform. But the answer _is_ correct. Just take a piece of paper and a pencil and draw the memory layout and you'll understand. BTW also try to change the values of `i_size` and `j_size`, the difference will still be 8. – Jabberwocky Dec 07 '18 at 16:21
  • @smielqf See my edit. There's no requirement that those address are adjacent. – dbush Dec 07 '18 at 16:49
  • @Jabberwocky I got the point of 8 bytes for a pointer in 64-bits OS, but I do not think that is what I want. And I update my question. Thanks. – smielqf Dec 07 '18 at 17:28
  • @smielqf I think the last paragraph of this answer applies. – Jabberwocky Dec 07 '18 at 17:32