I yesterday came across a question on SO, that wanted to dynamically allocate a 2-D array in C.
One of the answers was to allocate it this way:
int (*place)[columns] = malloc(rows * sizeof *place);
This apart from being beautiful, brought a question to my head. The question goes below:
Following is the code in which i allocate a 4×4
int (*arr)[4] = (int (*)[4]) malloc(4 * sizeof *arr);
printf("%d\n", sizeof arr); //Dynamic 2-D array by above method
int **arr1 = (int**) malloc(4 * sizeof(int*));
for(int i = 0; i < 4; i++)
arr1[i] = (int *) malloc(sizeof(double));
printf("%d\n", sizeof arr1); //Usual dynamic 2-D array
int *arr2 = (int*) malloc(4 * sizeof(int));
printf("%d\n", sizeof arr2); //Dynamic 1-D array
The usual output is:
4
4
4
However, if i try to print sizeof *arr, sizeof *arr1 and sizeof *arr2, the output is:
16
4
4
I don’t understand why this is happening. Any idea why the output for sizeof *arr is 16? How is the memory being being allocated in the first case?
Also, when i try to print the address of arr and *arr, both the printed values are same. *arr means "value at" arr. So does that mean arr stores its own address, i.e., it is pointing to itself (which i don’t think is possible)? Am slightly confused. Any idea where am I going wrong?
Thanks for your help!
where:
You must be working on a 32-bit machine, not a 64-bit machine.
The type of
arris ‘pointer to an array of 4int‘. When you dereference it, you get an ‘array of 4int‘. When passed tosizeof, the array is of size 16 (4 * sizeof(int)). Most of the time, when you reference an array, the type is adjusted to ‘pointer to zeroth element of the array’, butsizeof()is the primary exception to that rule; it sees an array as an array and returns the size of the whole array.The type of
arr1is ‘pointer to pointer toint‘. When you dereference it, you get a ‘pointer toint‘. When passed tosizeof, the pointer is of size 4 (sizeof(int *)).The type of
arr2is ‘pointer toint‘. When you dereference it, you get anint. When passed tosizeof, theintis of size 4.As James noted in his comment:
That is,
arr2is a pointer; the size of a pointer is 4 on a 32-bit machine.You can use either of these:
The first is a straight-forward 4×4 matrix. The result of
sizeof(mat1)will be 64 on a 32-bit machine (and most 64-bit machines, as it happens).The second is a pointer to a 4×4 matrix of
int. The result ofsizeof(mat2)will be 4 on a 32-bit machine;mat2is a pointer (to a 4×4 matrix ofint), so it is of size 4, the same as every other object pointer (and, in practice, the same size as every function pointer, though the C standard does not guarantee that function pointers and object pointers are the same size; POSIX does guarantee that, though).The result of
sizeof(*mat2)is the size of the object thatmat2points at, which is a 4×4 matrix ofint, so the size is 64 again.