【问题标题】:C passing by value or reference with pointersC 用指针传递值或引用
【发布时间】:2020-01-17 12:47:28
【问题描述】:

哪些函数调用是通过值传递的,哪些是通过引用传递的?

int *a;

int b;

int **c;

f(a);

g(&b);

h(*c);

只是简单的例子,我只是对指针以及如何判断它们如何传递感到困惑。

【问题讨论】:

  • 在C语言中,所有的函数参数都是按值传递的。只是有些值可能是指针。
  • 那么所有这些都是按值传递的?
  • 形式上,C 没有通过引用传递。它只有按值传递。如果您显式传递一个指针,则可以模拟通过引用传递(或者,如果您隐式传递一个指针,则可以通过尝试传递一个数组并将数组的值衰减为指向它的指针第一个元素)。所以更多的问题是您认为哪些参数是通过引用传递的。
  • 是的,它们都通过值传递int *
  • 好的,谢谢,但是&不代表是通过引用传递的吗?

标签: c function pointers reference


【解决方案1】:

为了让你的问题更清楚,让我们初始化变量

int b;

int *a = &b;

int **c = &a;

然后这个调用

f(a);

通过指针a 引用传递对象b。指针本身是按值传递的,即函数处理指针a的值的副本。

这个电话

g(&b);

实际上相当于之前的调用相对于接受的值。变量b 是通过引用传递的。

而且这个调用也相当于之前的调用

h(*c);

变量b通过指针*c引用传递,其值等于指针a的值。

所以所有三个函数都通过引用接受变量b

【讨论】:

    【解决方案2】:

    迂腐的答案是它们都是按值传递的,但有时该值是一个地址。

    更有用的是,假设您在这里没有错误,所有这些函数都是按地址传递的,这与 C 通过引用传递一样接近。它们接受一个指针作为参数,并且可以取消引用该指针以将数据写入它指向的任何位置。只有这些行对 g() 的调用是安全的,因为其他指针未定义。

    这是不需要重新分配的输入/输出参数的 C API 标准。

    需要返回一个新的可变大小缓冲区的函数通常接受一个指向指针的指针,因此它们可以取消引用参数以获取调用者中的地址,他们将指针写入他们分配的缓冲区,或者是函数的静态变量。

    正如 cmets 中提到的,可以只从函数中返回一个指针。没有它,内存分配在 C 中将无法工作。但是看到具有 size_t ** 参数或类似返回指针的函数仍然很常见。这可能主要是一种 Unix 模式,其中几乎每个函数都返回一个成功/错误代码,因此实际的函数输出会转移到参数。

    【讨论】:

    • 也许值得一提的是,我们不一定需要一个out参数作为指针的指针,但是或者可以简单地返回普通指针.. .
    【解决方案3】:

    形式上,C 没有按引用传递。它只有传值。

    您可以通过两种方式模拟引用传递:

    • 您可以将函数参数声明为指针,并显式使用& 将指针传递给调用者中的对象。
    • 您可以将函数参数声明为指针并传递一个数组,因为当您尝试传递一个数组时,实际发生的情况是该数组的值“衰减”为指向其第一个元素的指针。 (你也可以将函数参数声明为一个数组,让它看起来更像是一个正在传递的数组,但无论如何你实际上是在声明一个指针。)

    所以更多的问题是您认为哪些参数是通过引用传递的。

    你会经常听到它说“数组在 C 中通过引用传递”,这不是错误的,但可以说它也不是严格正确的,因为(如前所述)实际发生的是指向数组第一个元素的指针正在按值传递。

    【讨论】:

    • 通过引用传递数组:如果这完全正确,那么sizeof(arrayParameter) 将产生数组的大小,而不是指针的大小,不是吗? @Jolly_Jimmy:不要被我的评论弄糊涂了,它确实产生了指针的大小!
    【解决方案4】:

    最简单的判断方法是算术的大小,但char 类型并非如此。对于地址算术,调用sizeof operator,这与unsigned int 类型的普通算术不同。

    #include <iostream>
    using namespace std;
    
    int main() {
        unsigned int ui, *uiPtr;
    
        ui = 11;
        cout << ui << endl;
        ui += 1; //increases value by 1
        cout << ui << endl;
        uiPtr = &ui;
        cout << uiPtr << endl;
        uiPtr += 1; //increases value by sizeof
        cout << uiPtr << endl;
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2013-12-24
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      相关资源
      最近更新 更多