哪些类型通过引用传递,哪些类型按值传递?

时间:2012-11-08 15:17:32

标签: c types ref

如果我传递一个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);

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

结构怎么样?工会?指向它们的指针也通过了吗?

5 个答案:

答案 0 :(得分:4)

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

指针也通过值传递。只是当您复制指针时,您仍然可以修改指向的值,因此它与(通过引用传递)非常相似(但不完全相同)。

答案 1 :(得分:2)

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

答案 2 :(得分:2)

一切都按价值,期间传递。

不同之处在于C如何处理数组表达式。除非它是sizeof_Alignof或一元&运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,否则表达式为“N” -element数组T“将被转换(”衰减“)到类型为”T指针“的表达式,表达式的值将是数组的第一个元素的地址。

所以给出了像

这样的声明
int a[10] = {0};

只要表达式a出现在您的代码中&asizeof a_Alignof a以外的任何位置,它就会被转换为指针表达式和值表达式将是a[0]的地址,无论表达式是否传递给函数。

所以在像

这样的函数调用中
foo(a);

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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