2016-06-08 2 views
1
#include <stdio.h> 
#include <stdlib.h> 

void fun(int *arr) 
{ 
    arr=(int *)malloc(2*sizeof(int)); 
    arr[0]=5; 
    arr[1]=4; 
    printf("in fun {%d, %d}",arr[0],arr[1]); 
} 

void anotherFunction(int *arr) 
{ 
    arr[0]=4; 
    arr[1]=5; 
    printf("in fun {%d, %d}",arr[0],arr[1]); 
} 

int main(void) 
{ 
    int *arr,*emptyInMain; 
    int arr2[]={99,99}; 
    arr=(int *)malloc(2*sizeof(int)); 
    arr[0]=99; 
    arr[1]=99; 

    printf("arr "); 
    fun(arr); 
    printf("\narr in main {%d, %d}\n",arr[0],arr[1]); 

    printf("emptyInMain"); 
    fun(emptyInMain); 
    //printf("\narr in main {%d, %d}\n",emptyInMain[0],emptyInMain[1]); // WILL GIVE RUNTIME ERROR 
    printf("\n\--commented the line in the code because emptyInMain[0],emptyInMain[1] will give RUNTIME ERROR--"); 

    printf("\narr2"); 
    fun(arr2); 
    printf("\narr2 in main {%d, %d}\n",arr2[0],arr2[1]); 

    printf("\nfollowing output shows expected behaviour\n"); 

    printf("\narr2"); 
    anotherFunction(arr2); 
    printf("\narr2 in main {%d, %d}\n",arr2[0],arr2[1]); 
    return 0; 
} 

Мы все знаем, что передача массива в качестве аргумента является вызовом по ссылке. Как будто я посылаю массив arr = {99,99} функции, которая делает arr [0] = 4 и arr [1] = 5, значения также меняются на 4 и 5 в вызывающей функции. То же самое должно быть применимо, если я отправляю адрес переменной, а некоторые манипуляции выполняются в другой функции.Является ли массив аргументом в c действительно ссылочным типом?

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

arr in fun {5, 4} 
arr in main {99, 99} 
emptyInMainin fun {5, 4} 
--commented the line in the code because emptyInMain[0],emptyInMain[1] will give RUNTIME ERROR-- 
arr2in fun {5, 4} 
arr2 in main {99, 99} 

following output shows expected behaviour 

arr2in fun {4, 5} 
arr2 in main {4, 5} 

Только последний выход показывает изменение.

Почему я думаю, что arr не изменился в первых трех случаях, мы отправляем адрес arr, который хранится в локальной переменной fun(). Эта локальная переменная начинает указывать на какой-либо другой адрес после заявления:

arr=(int *)malloc(2*sizeof(int)); 

anotherFunction() является единственной функцией, которая не изменяет распределение собственной локальной переменной и манипулирует значение, хранящееся в его (локальной переменной) адрес.

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

+2

запомнить ключевой момент, C передает все параметры VALUE, даже ссылку. –

+3

@ scarecrow-, да, но еще один важный момент, чтобы помнить, что у C нет ссылок. –

+0

Если вы хотите, чтобы функция меняла значение своего аргумента, вы должны передать адрес аргумента в качестве аргумента в вызове и разыменовать _pointer_ внутри функции. – user3078414

ответ

3

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

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

Если вы хотите выделить массив в функции, и это повлияет на вызывающего абонента, есть два способа сделать это.

Во-первых, чтобы иметь функция возвращает указатель:

int *fun() { 
    int *localarr = malloc(2 * sizeof(int)); 
    localarr[0] = 4; 
    localarr[1] = 5; 
    return localarr; 
} 

Затем абонент будет делать:

arr = fun(); 

Второй способ передать указатель на указатель.

void fun(int **arrparam) { 
    int *localarr = malloc(2 * sizeof(int)); 
    localarr[0] = 4; 
    localarr[1] = 5; 
    *arrparam = localarr; 
} 

Затем абонент делает:

fun(&arr); 
+0

Не взять из этого прекрасного ответа, объясняющего 2 пути (возможно, другие exsit?) Для достижения более высокой цели OPs, он не отвечает на заголовок вопроса «Является ли массив аргументом в c действительно ссылочным типом?» - что составляет 1/2 шага от вопроса о священной войне. Предложите переименовать OP вопрос, чтобы он соответствовал цели: что-то вдоль линии, как передать информацию о массиве обратно вызывающему. – chux

+0

@chux Я решил ответить на вопрос в тексте, а не на вопрос в названии. – Barmar

+0

Да - это понятно, но это название, которое приводит людей к этому сообщению, и было бы лучше, если бы название соответствовало заданию вопроса OP и выбранному ответу. – chux

1

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

Для этого у вас есть указатель на указатель (это ваш двойной указатель).

foo(int** ptr) 
{ 
    *ptr = malloc(sizeof(int)*2); 
    (*ptr)[0] = 10; 
    (*ptr)[1] = 20; 
} 

int main() 
{ 
    int* ptr; 
    foo(&ptr); // Use the & operator to pass a pointer to the pointer. 

    // Check to make sure that the values are as expected. 
    assert(ptr[0] == 10); 
    assert(ptr[1] == 20); 

    // deallocate the memory 
    free(ptr); 
} 
Смежные вопросы