Нет, «Foo» является типом массива в обоих случаях, но когда указатель ожидается в выражении с «Foo», он неявно преобразован в один (который указывает на массив первого элемента). Все массивы имеют такое поведение. В случае, когда добавление может быть сделано с помощью типов указателей, но не с массивами, 'foo' преобразуется в 'int *'.
*(foo+2) // 'foo' is implicitly converted into 'int *', pointing to 'foo' first element
foo + 1 //same as above
Но теперь вы можете спросить, каковы свойства типа «массив» и почему мы должны когда-либо использовать его, а не неявный указатель на первый элемент гипс. Дело в том, что их не много.Вы можете сказать, размер объекта с типом массива, как это:
sizeof(foo) //returns the size which array 'foo' occupies
И получить его адрес с помощью «&» оператора:
&foo // '&foo' has type of 'int (*)[5]'
Вы также можете создавать функции с параметрами «массива '(или указатель), чтобы принимать только те, у которых заданный размер (что невозможно, если они являются просто указателями и ожидают, что массивы, переданные для распада, будут такими). Пример:
void func(int (&)[5]);
void func1(int (*arg)[5]); // should be accessed by '*arg', allow the use of null-pointers
void func2(int *); //same as the misleading 'void func2(int [5])' or 'void func2(int [6])' etc.
int foo[5];
int foo1[6];
func(foo); // 'foo' type is ('int [5]') - ok
func1(&foo); // '&foo' type is ('int (*)[5]') - ok
func(foo1); // 'foo1' type is ('int [6]') - not allowed, param type is 'int (&)[5]' !
func1(&foo1); // '&foo1' type is ('int (*)[6]') - not allowed, param type is 'int (*)[5]' !
func2(foo); // 'foo' is implicitly converted to 'int *' - ok
func2(foo1); // 'foo1' is implicitly converted to 'int *' - ok
Во втором случае, когда массив является 2D - применяются те же свойства. Это объявление означает следующее: «массив из 3 элементов с массивом типов из 4 элементов с типом int». Таким образом, это просто массив массивов и ничего больше. Это неявный указатель на преобразование первого элемента не относится к типу 'int **', а вместо 'int (*) [4]', поскольку каждый его элемент является другим массивом.
Заявление может быть написано так же:
int (foo[3])[4];
отметить также не могут быть назначены «массивы», поэтому они не могут быть переданы по значению или возвращаемый функциями. То, что я имею в виду:
int funcReturningArray()[2]; //not allowed
int funcAcceptingArray(int [2]); //just converted into pointer
int funcAcceptingArray(int *); //same as above
Хотя параметры массива синтаксически принято из-за унаследованных причинам (? Или потому, что что-то еще), их реальное значение никогда не переносится, и они просто «подгонялись» к указателям.
Примечание: Неявное преобразование типа массива в указатель его первого элемента иногда называют «Array to decander decay».
* Является ли foo действительно точкой для первого элемента массива? * - Нет, это массив. * Является ли foo теперь int \ * \ *? * - Нет, это 2D-массив. См. [Массивы] (http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c) – chris
@chris, поэтому, если бы я захотел перебрать его с помощью указателя, я бы нужно сделать 'int * ptr = & foo [0]'? – n0pe
@maxmackie 'int * ptr = foo' будет достаточно. –