Am I Correctly Understanding Pass By Value and Pass By Reference in C?

Tri*_*lla 2 c arrays pass-by-reference pass-by-value

In one of my course's tutorial videos, I have encountered a situation where pass by value and pass by reference is occurring. In the example he gives us, he, firstly, admits that the code is written poorly, and then asks us to find out what exactly would be printed. The relevant code is as follows:

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;
}
Run Code Online (Sandbox Code Playgroud)

What I want to make sure, after initially coming up with the wrong output, is that I'm understanding why the correct output of "10, 22" is being printed.

The value of 10 is being printed because when the set_int function is being called, its parameter, being a variable, means that any variable can be passed. It is not exclusive to only the value 22 as defined in the set_int function.

打印 22 的值是因为,在调用 set_array 函数时,它的参数是一个数组,这意味着只能传递原始值,因为它指向存储值 22 的特定内存位置。

我是否误解了正在发生的事情,我是否遗漏了任何关键点?

Sou*_*osh 10

根据定义,C 中的函数调用中没有按引用传递。您的两个示例都使用按值传递。但是,根据使用情况,结果会有所不同(即,我们可以模拟按引用传递的行为)。

  • 在第一种情况下,变量a是按值传递的,因此不能从函数调用中更改它。

  • 在第二种情况下,变量b是按值传递的,因此它也不能从函数调用中更改。

    然而,在第二种情况下,会发生一种特殊的现象。传递的参数b是一个数组。一个数组,虽然作为函数参数传递(以及许多其他用法),但会衰减为指向数组第一个元素的指针。所以本质上,您正在传递一个指针,并且可以修改指针指向的内存地址处的值(但不能修改指针本身)。这就是为什么,set_array()函数的更改仍然存在于main().

    换句话说,第二种情况等价于

    void set_pointer(int *ptr);
    void set_int(int x);
    
    int main(void){
        int a = 10; 
        int b[4] = {0, 1, 2, 3);
        int * p = &(b[0]);         // address of the first element
        set_int(a);
        set_pointer(p);           // pass the pointer
        printf("%d %d\n", a, b[0]);
    }
    
    void set_array(int *ptr){
        *ptr = 22;                 // operate on pointer
    }
    
    void set_int(int x){
        x = 22;
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 值得明确指出的是,使用数组语法声明函数参数实际上是将参数的类型声明为相应的指针类型,而不是数组。这个重要的微妙之处可能会令人困惑,因此我认为将参数声明为具有完整的数组类型是很糟糕的形式。 (2认同)
  • `set_array(b)` 通过引用传递 `b`。数组“b”未传递。传递对其的引用。不要将 C++ 使用“引用”作为某种语言功能的名称这一事实与“引用”是用于描述此功能的英语单词这一事实相混淆。指针引用它所指向的对象。`set_array(b)` 和 `void set_array(int array[4]) ...` 具有按引用传递的功能和行为。标准中将该机制指定为对指针的转换和调整这一事实并不能否定它是按引用传递的实现这一事实。 (2认同)