В C, когда имя массива используется в большинстве выражений, значение, которое используется в выражении, является адресом первого элемента массива, а его тип является указателем на тип этого элемента.Это остается верным, когда массив передается функции.Таким образом, даже если синтаксис C позволяет вам объявить:
void foo(int x[]);
Тип, который имеет x
, не является массивом int
, а указателем на int
.Итак, на самом деле это то же самое, что и:
void foo(int *x);
Для main
это будет означать, что:
int main(int argc, char *argv[]);
на самом деле совпадает с:
int main(int argc, char **argv);
Разрешение имени массива "распадаться" на тип указателя было функцией, уникально созданной для функций нового типа C, чтобы поддерживать обратную совместимость с предшествующими типами C.От Развитие языка C
... Например, записи каталога ранних систем Unix могут быть описаны в C как
struct {
int inumber;
char name[14];
};
Я хотел, чтобы структура не просто характеризовала абстрактный объект, но и описывала набор битов, которые могут быть прочитаны из каталога.Где компилятор может скрыть указатель на имя, требуемое семантикой?Даже если бы структуры рассматривались более абстрактно, а пространство для указателей могло бы быть каким-то образом скрыто, как я мог бы решить техническую проблему правильной инициализации этих указателей при выделении сложного объекта, возможно, такого, который указывал структуры, содержащие массивы, содержащие структуры на произвольную глубину?
Решение представляет собой решающий скачок в эволюционной цепочке между типизированным BCPL и типизированным C. Он устраняет материализацию указателя в хранилище и вместо этого вызывает создание указателя, когда имя массива упоминается в выражении.,Правило, которое сохраняется в сегодняшнем C, состоит в том, что значения типа массива, когда они появляются в выражениях, преобразуются в указатели на первый из объектов, составляющих массив.