Передать по значению возможно в C? - PullRequest
2 голосов
/ 25 августа 2011

Здравствуйте, я читал этот вопрос, я запутался в том, как мы можем передавать массивы по значению или нет. Вот фрагмент кода, который, я думаю, должен передавать массив по значению.

#include <cstdio>
void foo (int arr[]);
int main()
{
    int arr[10];
    foo(arr[10]);
    return 0;
}
void foo (int arr[])
{
.......
}

Скажите, пожалуйста, почему бы не пройти по значению?

Спасибо

Ответы [ 3 ]

7 голосов
/ 25 августа 2011

Массивы автоматически распадаются на указатели в определенных контекстах в C. Вызовы функций являются одним из таких мест. Тем не менее, вы передаете указатель по значению - C не имеет другого способа передачи параметров, кроме «по значению».

4 голосов
/ 25 августа 2011

Потому что это:

void foo(int arr[])

действительно просто синтаксический сахар для этого:

void foo(int *arr)

Поэтому, когда вы вызываете функцию, ваш массив превращается в указатель на первый элемент.

1 голос
/ 25 августа 2011

Короче говоря: вы не можете передать массив в качестве параметра функции и получить его как тип массива вызываемой функцией.Выражение массива в этом контексте будет преобразовано в тип указателя, прежде чем оно будет передано в функцию.

Из языка Си стандарт :

6.3.2.1 L-значения, массивы и указатели функций
...
3 За исключением случаев, когда это операнд оператора sizeof или унарный оператор & или строковый литерал, используемый для инициализациимассив, выражение с типом '' массив из тип '' преобразуется в выражение с указателем типа '' на тип '', указывающее на начальный элемент объекта массиваи не является lvalue.Если объект массива имеет класс хранения регистров, поведение не определено.

Это означает, что когда вы пишете что-то вроде

int arr[10];
foo(arr);

выражение arr в вызове foo немедленно преобразуется в указатель типа;говорят, что "распад" набрать int *.Таким образом, все, что foo когда-либо получит, это значение указателя.

Более стандартный язык:

6.7.5.3 Деклараторы функций (включая прототипы)
...
7 Объявление параметра в виде массива '' type '' должен быть скорректирован на '' квалифицированный указатель на type '', где квалификаторы типа (если таковые имеются) - те, которые указаны в [ и ]вывод типа массива.Если ключевое слово static также присутствует в пределах [ и ] деривации типа массива, то при каждом вызове функции значение соответствующего фактического аргумента должно обеспечивать доступ к первому элементу массива с atкак минимум столько же элементов, сколько указано в выражении размера.

Это означает, что если ваш прототип для функции foo равен

void foo(int arr[])

или

void foo(int arr[10])

это будет интерпретировано как

void foo(int *arr)

Опять же, определение языка таково, что вы не можете передать выражение массива в качестве параметра функции и получить его как массиввведите вызываемой функцией.

Есть способы обойти это;вы можете обернуть массив в struct и передать struct по значению, например, так:

struct T { int arr[10]; } var;
foo(var);
...
void foo (struct T arg) { ... }

Когда хаки идут, это на самом деле не приносит вам большой выгоды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...