Может кто-нибудь объяснить мне, пожалуйста, почему это происходит?
С ...
int* foo[2] = {arr1, arr2}; // Let's say the length of arr1 is 3 and arr2 is 1
... foo
объявляется как массив, элементы которого имеют тип int *
. Вы не представляете определения arr1
и arr2
, но допустим, что они являются массивами int
- тогда в выражениях инициализатора они «распадаются» на указатели на свои первые элементы, которые имеют правильный тип для элементов foo
, так что все в порядке.
Но указатели не целые числа. Вы объявляете pFoo
как int *
, но инициализируете его int **
, преобразованным в int *
:
int* pFoo = (int*)foo;
Преобразование типа указателя ничего не делает с данными, на которые он (фактически) указывает, и поскольку pFoo
в конечном итоге указывает на данные, которые на самом деле не int
s, доступ к этим данным через pFoo
приводит к неопределенному поведению .
Возможно, вы искали это:
int **pFoo2 = foo; // note: no cast needed
Теперь тип pFoo2
, int **
, совпадает с типом, к которому foo
естественным образом распадается, и вы можете правильно получить доступ к элементам:
printf("%d", pFoo2[0][0]);
Обратите внимание, что вы по-прежнему обращаетесь к arr1
и arr2
через pFoo2
, косвенно. Вы все равно должны уважать их длину, даже если эти длины не совпадают друг с другом и не очевидны для типа pFoo2
или foo
.