Ответ 1
Сначала, standardese:
6.7.5.3 Объявление функций (включая прототипы)
...
7 Объявление параметра как '' массива type должно быть скорректировано на '' квалифицированный указатель на type, где квалификаторы типа (если они есть) - это те, которые указаны в[
и]
тип массива. Если ключевое словоstatic
также появляется в пределах[
и]
тип массива, то для каждого вызова функции значение соответствующего фактический аргумент должен обеспечивать доступ к первому элементу массива, по меньшей мере, столько же элементы, указанные выражением размера.
Таким образом, любой параметр функции, объявленный как T a[]
или T a[N]
, обрабатывается так, как если бы он был объявлен T *a
.
Итак, почему параметры массива обрабатываются так, как если бы они были объявлены как указатели? Вот почему:
6.3.2.1 Lvalues, массивы и обозначения функций
...
3 За исключением случаев, когда это операнд оператораsizeof
или унарный оператор&
, или строковый литерал, используемый для инициализации массива, выражение, которое имеет тип '' массив type, является преобразованный в выражение с типом '' указатель на type, который указывает на начальный элемент объект массива и не является значением lvalue. Если объект массива имеет класс хранения регистров, поведение undefined.
С учетом следующего кода:
int main(void)
{
int arr[10];
foo(arr);
...
}
В вызове foo
выражение массива arr
не является операндом либо sizeof
, либо &
, поэтому его тип неявно преобразован из "10-элементного массива int
" в "указатель на int
" в соответствии с 6.2.3.1/3. Таким образом, foo
получит значение указателя, а не значение массива.
Из-за 6.7.5.3/7 вы можете написать foo
как
void foo(int a[]) // or int a[10]
{
...
}
но он будет интерпретироваться как
void foo(int *a)
{
...
}
Таким образом, две формы идентичны.
Последнее предложение в 6.7.5.3/7 было введено с помощью C99 и в основном означает, что если у вас есть объявление параметра, например
void foo(int a[static 10])
{
...
}
фактический параметр, соответствующий a
, должен быть массивом с не менее чем 10 элементами.