2011-01-23 2 views
35

Ниже приведен фрагмент из книги C Программирование Просто ответы на часто задаваемые вопросы. Разве это не так, потому что массивы никогда не могут быть переданы по ссылке?Передача массива функции по значению

VIII.6: Как вы можете передать массив функции по значению?

Ответ: Массив может быть передан в функцию по значению путем объявления в вызываемой функции имя массива с помощью квадратных скобок ([ и ]) , прикрепленных к концу. При вызове функции просто передайте вызываемой функции массив (то есть имя массива) . Например, следующая программа передает массив со x[] к функции с именем byval_func() по значению:

Параметр int[] говорит компилятору, что функция byval_func() будет принимать один аргумент- в массив целых чисел. Когда функция byval_func() называется, вы передать адрес массива byval_func():

byval_func(x); 

Поскольку массив передается по значения, точная копия массива сделаны и размещены на стек. Затем вызываемая функция принимает эту копию массива и может распечатать его. Поскольку массив передается byval_func() является копией исходного массива, модифицируя массив в функции byval_func() не имеет никакого влияния на исходный массив.

+0

Это верно для structs - вы можете передавать их по значению (по стеку) или по ссылке, но не для массивов. – sinelaw

+13

Это в книге о C, правда? Я вижу, что это датируется 1995 годом, но тогда это было уже неправильно. –

+24

Если это то, что говорится в книге, вам нужно отбросить книгу - она ​​содержит серьезную дезинформацию по основной проблеме, и кто знает, какая другая дезинформация о других проблемах. Последний цитируемый абзац абсурд - если вы изменяете массив в вызываемой функции, вы также изменяете массив в вызывающей функции, потому что массивы не передаются по значению в C. –

ответ

53

Поскольку массив передается по значению, точная копия массива производится и помещается в стек.

Это неверно: сам массив не копируется, только копию указателя на его адрес передается вызываемому абоненту (помещенного в стек). (Независимо от того, объявляете ли вы параметр int[] или int*, это decays into a pointer.) Это позволяет вам изменять содержимое массива из вызываемой функции. Таким образом, это

Поскольку массив, переданный в byval_func(), является копией исходного массива, изменение массива в функции byval_func() не влияет на исходный массив.

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

+0

Я думаю, что вы правы , – sinelaw

+0

Он действительно есть. В C++ вы, конечно, можете иметь объекты массива, переданные по значению, но в C массив - это просто указатель. –

+4

StefanHållén: Вы не можете передавать (или возвращать) массивы по значению в C или C++, вы можете передавать массивы по ссылке в C++, потому что C++ имеет ссылочные типы. –

45

Запишите эту книгу.Если вам нужен реальный C-FAQ, который не был написан программистом-новичком, используйте его: http://c-faq.com/aryptr/index.html.

Синтаксис-накрест, строго говоря, вы не может передать массив по значению в С.

void func (int* x); /* this is a pointer */ 

void func (int x[]); /* this is a pointer */ 

void func (int x[10]); /* this is a pointer */ 

Однако, для записи есть подвох в C, который действительно позволяет Вам передать массив по значению в C. Не пытайтесь это дома! Потому что, несмотря на этот трюк, по-прежнему нет причин передавать массив по значению.

typedef struct 
{ 
    int my_array[10]; 
} Array_by_val; 

void func (Array_by_val x); 
+5

Косметика для третьего примера означает, что вы можете сделать 'sizeof (array)/sizeof (array [0])' в функции – Ulterior

+1

@Ulterior Не было бы хорошо, если бы это сработало? Но, увы, вы ошибаетесь, стандарт C не настолько умный. Попробуйте это: 'void func (int arr [10]) {printf (« Нет, я все еще указатель, мой размер -% d. », Sizeof (arr)); } '. Он будет печатать 4 или 8 на ПК, а не 40, как и следовало ожидать. – Lundin

+1

«Потому что, несмотря на этот трюк, по-прежнему нет причин передавать массив по значению». -- Зачем? – Antinous

1

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

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

+17

Структуры и союзы могут передаваться по значению. –

-11
#include<stdio.h> 
void fun(int a[],int n); 
int main() 
{ 
    int a[5]={1,2,3,4,5}; 
    fun(a,5); 
} 
void fun(int a[],int n) 
{ 
    int i; 
    for(i=0;i<=n-1;i++) 
     printf("value=%d\n",a[i]); 
} 

С помощью этого метода можно передать массив по значению, но на самом деле массив доступ через его базовый адрес, который на самом деле копирование в стеке.

+2

Нет, это делает * не * передают массив по значению. Параметр - это указатель. –

+0

И если 'fun' изменил значение' a [0] ', это изменение будет видно в' main'. –

+0

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

Смежные вопросы