Для начала типичной ошибкой тех, кто не знает C, является следующее утверждение:
C не передает ничего по ссылке, не имеет ссылок
C не имеет ссылок в том смысле, как в C ++, но имеет механизм передачи по ссылке .
Вы не должны смешивать терминологию и понятия разные языки и должны использовать терминологию, определенную в конкретном языке.
В C указатели играют роль ссылок. Из C Standard
- тип указателя может быть получен из типа функции или типа объекта, называемого ссылочным типом. Тип указателя описывает объект, значение которого предоставляет ссылку на объект ссылочного типа . Тип указателя, полученный из ссылочного типа T, иногда называют «указателем на T». Конструкция типа указателя из ссылочного типа называется «выводом типа указателя». Тип указателя является полным типом объекта.
Таким образом, передача по ссылке в C означает передачу объекта через указатель на объект.
Что касается вашего вопроса, то массивы используемые в выражениях (за редким исключением, как, например, использование в операторе sizeof) неявно преобразуются в указатели на их первые элементы.
Вы можете представить себе следующий вызов функции
void f( int a[] );
//...
int a[] = { 1, 2, 3, 4, 6 };
f( a );
like
void f( int a[] );
//...
int a[] = { 1, 2, 3, 4, 6 };
int *tmp = a;
f( tmp );
или то же самое
void f( int a[] );
//...
int a[] = { 1, 2, 3, 4, 6 };
int *tmp = &a[0];
f( tmp );
С другой стороны, параметр функции, имеющий тип массива, неявно корректируется компилятором для указания на тип элемента массива .
Так, например, эти два объявления функций эквивалентны и объявляют одну и ту же функцию
void f( int a[] );
void f( int *a );
Таким образом, передавая массив функции, вы передаете указатель на ее первый элемент. Это означает, что фактически все элементы массива передаются по ссылке. Используя арифметику указателя c, вы можете изменить любой элемент массива, на который указывает указатель.
Например, этот оператор
arr[1] = 10;
оценивается компилятором как
*( arr + 1 ) = 10;
где arr - указатель на первый элемент массива.