Во-первых, массив, переданный функции, фактически передает указатель на первый элемент массива, например, если у вас есть
int a[] = { 1, 2, 3 };
f(a);
Затем, f()
получает &a[0]
, переданный ему.Таким образом, при написании прототипов вашей функции следующее эквивалентно:
void f(int arr[]);
void f(int *arr);
Это означает, что размер массива потерян, и f()
, в общем, не может определить размер.(По этой причине я предпочитаю void f(int *arr)
форму, а не void f(int arr[])
.)
В двух случаях f()
информация не требуется, и в этих двух случаях нормально не иметьдополнительный параметр к нему.
Во-первых, в arr
есть специальное согласованное значение, которое и вызывающий, и f()
принимают за "конец".Например, можно согласиться, что значение 0
означает «Готово».
Тогда можно написать:
int a[] = { 1, 2, 3, 0 }; /* make sure there is a 0 at the end */
int result = f(a);
и определить f()
что-то вроде:
int f(int *a)
{
size_t i;
int result = 0;
for (i=0; a[i]; ++i) /* loop until we see a 0 */
result += a[i];
return result;
}
Очевидно, что приведенная выше схема работает только в том случае, если и , вызывающий и вызываемый стороны согласны с соглашением и следуют ему.Примером является strlen()
функция в библиотеке C.Он вычисляет длину строки, находя 0
.Если вы передадите ему что-то, что не имеет 0
в конце, все ставки выключены, и вы находитесь на неопределенной территории поведения.
Второй случай, когда у вас на самом деле нетмассив.В этом случае f()
получает указатель на объект (int
в вашем примере).Итак:
int change_me = 10;
f(&change_me);
printf("%d\n", change_me);
с
void f(int *a)
{
*a = 42;
}
в порядке: f()
все равно не работает с массивом.