arrayscpointersdynamic-memory-allocationsizeof

Why is malloc allocated array shows less size than static allocated array


Why is arr1 size less than arr2, am I missing something? Does it have to do something with malloc and stack, heap?

#include <malloc.h>
#include <stdio.h>

int main(void)
{
    int length = 4;
    int *arr1 = (int*)malloc(length*sizeof(int));

    int arr2[length];
    arr2[0] = 10;
    arr2[1] = 20;
    arr2[2] = 30;
    arr2[3] = 40;

    arr1 = arr2;

    for (int i = 0; i<length; printf("%d\n", arr1[i++])) ;

    printf("Size of arr %lu\n", sizeof(arr1));
    printf("Size of arr2 %lu\n", sizeof(arr2));
    printf("Size of int %lu", sizeof(int));    
}

Output:

$ gcc -g new.cpp && ./a.out
10
20
30
40
Size of arr 8
Size of arr2 16
Size of int 4

I was expecting to have arr1 and arr2 both have 16 byte size.


Solution

  • The variable arr1 declared like

     int *arr1 = (int*)malloc(length*sizeof(int));
    

    has the pointer type int * while the variable arr2 declared as a variable length array

    int arr2[length];
    

    has the type int[4].

    So the expression sizeof( arr1 ) that is equivalent to sizeof( int * ) yields the size of the pointer itself.

    Pay attention to that your program has a memory leak because a memory was allocated and its address was stored in the pointer arr1 and then the pointer arr1 was reassigned

    arr1 = arr2;
    

    The array arr2 used as an expression in the above assignment statement is implicitly converted to a pointer to its first element. That is the above statement in fact is equivalent to

    arr1 = &arr[0];
    

    Also to output a value of the type size_t you should use conversion specification %zu because the C Standard accepts that it is not necessary that the type unsigned long is an alias for the type size_t..

    From the C Standard (7.19 Common definitions <stddef.h>)

    4 The types used for size_t and ptrdiff_t should not have an integer conversion rank greater than that of signed long int unless the implementation supports objects large enough to make this necessary

    Also if you wil write for example sizeof( arr2 + 0 ) then again the expression will yield the size of a pointer because in this expression arr2 + 0 with the pointer arithmetic the array arr2 is implicitly converted to a pointer to its first element.