【问题标题】:C pass array by value vs pass array by referenceC 按值传递数组与按引用传递数组
【发布时间】:2020-04-19 22:22:31
【问题描述】:

大家好,所以我一直在学习 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

基本上我的问题是为什么从 set_array 函数传递的 22 重写 b 数组上的 0 并实际打印但从 set_int 函数传递的 22 没有被传递或打印。

谢谢大家!

【问题讨论】:

  • C 中没有“通过引用”——void set_array(int array[4]) 实际上是void set_array(int* array)
  • array 衰减到 set_array 中的指针。 [] 实际上是一个指针解引用。所以要使set_int 等同于set_array 它更像是:void set_int(int *x) { *x = 22; }
  • C 中的 Everything 都是按值传递的。唯一的区别是该值采用什么形式。对于数组,它们的表达值是指向第一个元素的指针。
  • @kaylum 所以基本上它只会覆盖值如果指向一个数组,比如在 set_array 函数中,对吧?
  • 您没有接受解决问题的两个答案之一,为什么?

标签: c arrays pass-by-reference implicit-conversion function-declaration


【解决方案1】:

在 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

即我们直接将对象x传递给函数f。因此该函数处理对象x 的副本。更改副本不会影响 main 中声明的原始对象 x

对于函数g,它通过指向它的指针间接访问对象x。所以改变指向的对象我们改变了在main中声明的对象x

对于数组,当数组传递给函数时,它会隐式转换为指向其第一个元素的指针。所以这个函数实际上是通过这个指针通过引用来获取数组的元素。使用指针和指针算法我们可以改变数组的任何元素。

这个函数声明

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] );

因为在表达式中使用的数组(例如作为函数参数表达式)被隐式转换为指向它们的第一个元素的指针。

【讨论】:

  • 所以在简历中起作用了,因为我分配的新值被定向到一个指针中,在这种情况下是数组,对吗?
  • @diego 数组被转换为指向其第一个元素的指针,并在函数中使用此指针,您可以直接访问数组的元素,例如通过应用下标运算符 array[i] where i是一些索引。
【解决方案2】:

C 函数,当接收数组和指针以外的参数时(数组实际上被转换为指针)不会更新源值,因为它们创建了一个 副本参数传递的值。

你的功能应该是:

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

然后您正在使用源变量。但是由于你没有声明一个指针,而是一个变量,你必须这样称呼它:

set_int(&a);

为了确保您传递的是内存引用,而不是它的内容。

【讨论】:

  • 你需要尊重x:*x = 22
  • “数组和指针除外”。虽然我明白你想说什么,但这种说法在技术上并不正确。在 C 中,一切都是按值传递的——甚至是指针和数组。这意味着数组和指针也不能在函数内部更改。只能更改指针/数组引用的内存,而不能更改指针/数组本身。这确实经常让新的 C 编码人员感到困惑,但这是一个非常重要的区别。
  • @kaylum:数组不是按值传递的。
猜你喜欢
  • 2023-03-02
  • 2011-05-08
  • 1970-01-01
  • 2021-09-14
  • 2012-05-06
  • 1970-01-01
  • 2014-09-30
相关资源
最近更新 更多