Reputation: 23
why i can cast from int** to int* with two-dimensional array, but not with pointer array?
so for exmple why when i do this:
int arr2d[3][3] = { { 1, 2, 3}, { 4, 5, 6}, { 7, 8, 9} };
int* arr = (int*)arr2d;
int i = 0;
for (i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
it works and prints: 1 2 3 4 5 6 7 8 9
but when i do this:
int arr1[] = { 11, 12 };
int arr2[] = { 13, 14, 15, 16 };
int arr3[] = { 17, 18, 19 };
int* pArr[3] = { arr1, arr2, arr3 };
int* pArr1d = (int*)pArr;
for (i = 0; i < 9; i++)
{
printf("%d ", pArr1d[i]);
}
it doesn't work and prints: 4192000 4191976 4191956 -858993460 -858993460 17 18 19 -858993460
Upvotes: 0
Views: 254
Reputation: 44300
pArr
is an array of 3 pointers to int.
When used in an expression pArr
will be converted to a pointer to pointer to int and point to the initial element of the array (which is a pointer to int).
So when you do:
int* pArr1d = (int*)pArr;
You convert a "pointer to pointer to int" to a "pointer to int". The types are not compatible. Once you dereference the casted pointer, it's undefined behavior.
And when you print it you do two violation which is also undefined behavior.
You print pointers as if they were integers.
You access the array out of bounds.
Upvotes: 1
Reputation:
It is not int **
in the first case.
(int*)pArr
is just a violent cast, not some constructor.
The first version warns with int *arr = arr2d;
(no cast)
warning:
initialization of 'int *' from incompatible pointer type 'int (*)[3]'
Incompatible maybe, but it is just that the arr2d
has the ints in packs of 3, but back to back. Similar the inner braces are not necessary here (no gaps):
int arr2d[][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Also the first dimension can be left out. int [][3]
corresponds to int (*)[3]
.
The pointer version gives this warning with int* pArr1d = pArr;
warning:
initialization of 'int *' from incompatible pointer type 'int **'
Dereferencing (pArr1d[i]
) tries to access the i
-th integer (of 9) at pArr1d
--- but there are only 3 pointers there. So you can't simply flatten it out like above. (But now the three rows can have different sizes)
This works! The three arrays are one after the other (on the stack):
int arr1[] = { 11, 12 };
int arr2[] = { 13, 14, 15, 16 };
int arr3[] = { 17, 18, 19 };
for (int i = 0; i < 9; i++)
{
printf("%d ", arr1[i]);
}
The debugger illustrates:
(gdb) p pArr
$13 = {0x7fffffffe87c, 0x7fffffffe890, 0x7fffffffe884}
(gdb) x/12 arr1
0x7fffffffe87c: 11 12 17 18
0x7fffffffe88c: 19 13 14 15
0x7fffffffe89c: 16 -6020 32767 -6000
(gdb) x/12 arr2
0x7fffffffe890: 13 14 15 16
0x7fffffffe8a0: -6020 32767 -6000 32767
0x7fffffffe8b0: -6012 32767 -1022695680 287912987
(gdb) x/12 arr3
0x7fffffffe884: 17 18 19 13
0x7fffffffe894: 14 15 16 -6020
0x7fffffffe8a4: 32767 -6000 32767 -6012
pArr
holds three addresses - not integers.
Upvotes: 0