C передать массив по значению или передать массив по ссылке - PullRequest
1 голос
/ 20 апреля 2020

Привет всем, поэтому я изучил C, и я натолкнулся на этот пример, и я действительно не нахожу логи c позади. это не технический вопрос относительно кода, который я искал больше для объяснения. это код

#include <stdio.h>

void set_array(int array[4]);
void set_int(int x);

int main(void)
{
    int a = 10;
    int b[4] = {0, 1, 2, 3};
    set_int(a);
    set_array(b);
    printf("%d %d\n", a, b[0]);
}

void set_array(int array[4])
{
    array[0] = 22;
}

void  set_int(int x)
{
    x = 22;
}

вывод 10 22

в основном мой вопрос: почему 22, переданный из функции set_array, переписывает 0 в массив b и фактически печатает но 22, который передается из функции set_int, не передается и не печатается.

Спасибо всем!

Ответы [ 2 ]

4 голосов
/ 20 апреля 2020

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

Сравните два вызова функции в этой демонстрационной программе.

#include <stdio.h>

void f( int x )
{
    x = 10;
}

void g( int *x )
{
    *x = 10;
}


int main(void) 
{
    int x = 0;

    printf( "Before call f: x = %d\n", x );

    f( x );

    printf( "After  call f: x = %d\n", x );

    putchar( '\n' );

    printf( "Before call g: x = %d\n", x );

    g( &x );

    printf( "After  call g: x = %d\n", x );

    return 0;
}

вывод программы

Before call f: x = 0
After  call f: x = 0

Before call g: x = 0
After  call g: x = 10

То есть мы напрямую передали функции f объект x. Таким образом, функция имеет дело с копией объекта x. Изменение копии не влияет на исходный объект x, объявленный в main.

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

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

Это объявление функции

void set_array(int array[4]);

эквивалентно следующему объявлению

void set_array(int array[]);

и оба объявления корректируются компилятором в соответствии с объявлением

void set_array(int *array);

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

Вызов функции set_array в вашей программе

set_array(b);

эквивалентен следующему вызову

set_array( &b[0] );

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

0 голосов
/ 20 апреля 2020
Функции

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

Если ваша функция:

void  set_int(int *x)
{
    x = 22;
}

Затем вы работаете с исходной переменной. Но так как вы объявили не указатель, а переменную, вам придется вызывать его следующим образом:

set_int(&a);

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

...