В обоих случаях, когда переменная, как вы говорите, передается функции или массив передается функции, передается значение .
Но в первом случае передается значение переменной, в то время как во втором случае передается значение указателя на первый элемент массива.
Массивы, используемые в выражениях с редкими исключениями, преобразуются в указатели на свои первые элементы.
Из C стандарта (6.3.2.1 L-значения, массивы и обозначения функций)
3 За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или является строковым литералом, используемым для инициализации массива, выражение с типом '' массив типа '' преобразуется в выражение с типом '' указатель на тип '', которое указывает на начальный элемент объекта массива и не является lvalue. Если объект массива имеет класс хранения регистров, поведение не определено.
Таким образом, имея указатель на объект, вы можете изменить указанный объект.
Предположим, что у вас есть две функции .
void f( int x )
{
x = 10;
}
and
void g( int *px )
{
*px = 10;
}
и их вызовы
int n = 0;
f( n );
g( &n );
Вы можете представить определения функций и их вызовы следующим образом
int n = 0;
f( n );
g( &n );
// ...
void f( /* int x */ )
{
int x = n;
x = 10;
}
void g( /* int *px */ )
{
int *px = &n;
*px = 10;
}
То есть обе функции имеют дело с копиями значений выражений, используемых в качестве аргументов функции. Но в случае функции g
, поскольку функция получает значение адреса указанного объекта n
, вы можете изменить указанный объект n
, используя указатель (адрес).
В терминах C Передача объекта в функцию косвенно через указатель на объект называется передачей по ссылке.
Из C Стандарт
- Тип указателя может быть происходит от типа функции или типа объекта, называемого ссылочным типом. Тип указателя описывает объект, значение которого предоставляет ссылку на объект ссылочного типа. Тип указателя, полученный из ссылочного типа T, иногда называют «указателем на T». Конструкция типа указателя из ссылочного типа называется «выводом типа указателя». Тип указателя является полным типом объекта.
Обратите внимание на то, что объявление функции, подобное этому
void f( int a[], size_t n );
, эквивалентно следующему объявлению
void f( int *a, size_t n );
И оба объявляют одну и ту же функцию.
Если у вас есть массив, как, например,
#define N 10
//...
int a[N];
, то он передается в функцию, такую как
f( a, N );
затем, как следует из первой кавычки из стандарта C, указатель массива преобразуется в указатель на его первый элемент. И имея этот указатель в функции, вы можете изменить любой элемент массива, потому что каждый элемент массива фактически передается по ссылке. Используя арифметику указателя c, вы можете изменить любой элемент указанного массива. Например
void f( int *a, size_t n )
{
for ( int i = 0; i < n; i++ )
{
a[i] = i;
// that is the same as
// *( a + i ) = i;
}
}