【问题标题】:Which types pass by reference and which by value?哪些类型通过引用传递,哪些通过值传递?
【发布时间】:2012-11-08 15:17:32
【问题描述】:

如果我传递一个 int,它将按值传递。
void something(int i)
如果我传递某种类型的数组,它将通过引用传递。
void something(int i[])
或者 void something(int *i);

像 int 这样的类型将通过值传递,数组将作为引用传递。

第一个问题是,是否还有其他类型会通过引用传递?
第二个问题是,数组(int i[])的第一遍和第二遍(int *i)有什么区别?

编辑: 我会澄清我的问题。 您传递给函数的其他类型(例如数组)将在函数内部进行更改。 (正如您所解释的,这不完全是通过引用传递)。

void something(int i[])
{
i[0]=5;
}

something(i);

这不仅会在本地更改数组。

结构呢?工会?指向它们的指针也通过了?

【问题讨论】:

    标签: c types ref


    【解决方案1】:

    一切都按值传递,句号。

    区别在于 C 如何处理数组表达式。除非它是 sizeof_Alignof 或一元 & 运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则类型为“@987654324 的 N 元素数组”的表达式@" 将被转换 ("decay") 为类型为 "pointer to T" 的表达式,表达式的值将是数组第一个元素的地址。

    所以给定一个类似的声明

    int a[10] = {0};
    

    只要表达式a出现在代码中除&asizeof a_Alignof a之外的任何位置,它将被转换为指针表达式,表达式的值将是@987654331的地址@,无论表达式是否被传递给函数。

    所以在像这样的函数调用中

    foo(a);
    

    表达式a 被转换为指针表达式,指针表达式的值 (&a[0]) 被传递给函数。

    同样,在函数参数声明中,T a[]T a[N] 被解释为T *a;无论数组表示法如何,参数都被声明为指针,而不是数组。

    【讨论】:

      【解决方案2】:

      在 C 中,所有类型都按值传递。数组实际上不会在函数调用中传递——当你声明一个数组参数时,编译器会默默地用一个指针替换数组,当你调用它时,你传递地址数组的第一个元素。

      指针也按值传递。只是当你复制一个指针时,你仍然可以修改指向的值,所以它与pass-by-reference非常相似(但不完全相同)。

      【讨论】:

      • 谢谢你的回答,我澄清了我的问题。
      【解决方案3】:

      C 中的一切 都是按值传递的。数组不是通过引用传递的,而是衰减为一个指针,与所有其他指针一样,它是按值传递的。

      按值传递指针意味着它所保存的地址被复制,并且在您使用此副本操作的函数中,该副本指向与外部指针相同的数据。但是,尝试在函数内更改指针本身的值不会影响调用者传递的指针:

      void fn (int *ptr)
      {
        // this is OK and the data that the pointer points to will be updated, 
        // even though the pointer itself is a copy
        *ptr = 5;
      
        // this will not have an effect out of the function since ptr is merely a copy
        ptr = NULL;
      }
      

      在上面的示例中,如果要更改 ptr 的值,则必须将函数声明为具有 int ** 参数,而不是 int *

      void fn (int **ptr)
      {
        *ptr = NULL;
      }
      ...
      int *x;
      // at this point, x is uninitialised
      fn(&x);
      // x is now NULL
      

      【讨论】:

      • 谢谢你的回答,我澄清了我的问题。
      【解决方案4】:

      所有类型都按值传递,但(在函数调用上下文中)数组名的值是第一个元素的地址。

      【讨论】:

      • 谢谢你的回答,我澄清了我的问题。
      【解决方案5】:

      您能想到的任何数据类型(甚至是您枚举的数据类型)都可以作为引用或值传递。

      【讨论】:

      • 谢谢你的回答,我澄清了我的问题。
      猜你喜欢
      • 2019-01-04
      • 2021-11-18
      • 2017-05-16
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 2019-05-18
      • 2013-04-21
      • 1970-01-01
      相关资源
      最近更新 更多