数组是按值传递还是按引用传递?

AR8*_*R89 11 c arrays string pointers

我肯定知道

function(int *a); function(int a[]);
Run Code Online (Sandbox Code Playgroud)

在C中是相同的,函数(int a [])将被转换为函数(int*a)

int *a = malloc(20);
int b[] = {1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)

这两个不一样,第一个是指针,第二个是数组.当我调用函数(b)时会发生什么?(函数(int*a))我知道b在堆栈上,那么如何传递给该函数?

其次,字符串:

char *c1 = "string";
char c2 [] = "string";
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我不知道c1在哪里,我想c2在堆栈上.假设函数现在是:function(char*c),它与函数(char c [])相同,当我调用函数(c1)和函数(c2)时会发生什么,字符串将通过引用传递或值?

iab*_*der 18

有一个关键点,使这里,一切都是真的通过了由价值为例,这将传递一个副本afoo()(这恰好是一个指向一些内存):

int *a = malloc(20);
foo(a);
Run Code Online (Sandbox Code Playgroud)

这就是为什么如果你做这样的事情,foo()它并没有真正改变指针a,main()但改变了本地副本:

foo(int *a)
{
  a = NULL; /*changes local copy of the pointer*/
}
Run Code Online (Sandbox Code Playgroud)

换句话说,您可以使用foo()本地副本a来更改"a" 指向的内存,但不能更改a 指向的内容main().

现在,为了传递"通过引用"的东西,你将一个指向指针的副本传递给函数(类似于a-> b-> memory):

int *a = malloc(20);
foo(&a);
Run Code Online (Sandbox Code Playgroud)

因此,当您分配给它时foo(),更改指针main():

foo(int **a)
{
  *a = NULL; /*changes the pointer in main */
}
Run Code Online (Sandbox Code Playgroud)

现在回答一些其他问题,当您使用数组名称时,它将转换为指向数组第一个元素的指针:

int *a = malloc(20);
int b[] = {1,2,3,4,5};
foo(a);
foo(b);
Run Code Online (Sandbox Code Playgroud)

最后两个函数调用是等效的,因为它们都将指针传递给某个内存的第一个元素,区别在于a堆上分配的内存,b然而,内存是在堆栈上分配的.

最后,字符串,下面是类似的,就是同样的原则也适用,但第一个是一个常量字符串文字和应该被定义为const,你应该不会尝试任何地方修改它,但你可以改变第二个:

const char *c1 = "string";
char c2 [] = "string";
Run Code Online (Sandbox Code Playgroud)

 

  • 虽然这是正确的,但对于初学者来说,它并不是真正的教学法.最好声明`func(int x)`是值,而`func(int*x)`是引用.因为它是由val还是由ref实际上取决于函数的_intention_.否则,可以说你的例子`foo(int**a)`没有通过引用传递任何东西,它只是通过值传递指针指针. (4认同)
  • @Lundin我认为,恕我直言,说通过引用传递的东西是所有初学者尝试分配给函数内部的指针并期望它在其他地方改变它的原因. (2认同)
  • 与学习 C 语言的 Java 程序员相比,没有程序员经验的初学者可能不太可能这样做。无论如何,所有初学者也会尝试从函数返回指向局部变量的指针。我觉得像“通过引用”或“指针”这样的模糊术语对初学者来说并没有真正的帮助,最好解释一下二进制文件中发生的事情。 (2认同)

Sha*_*ash 5

来自K&R2

When an array name is passed to a function, what is passed is the 
location of the initial element. Within the called function, this 
argument is a local variable, and so an array name parameter is a 
pointer, that is, a variable containing an address.
Run Code Online (Sandbox Code Playgroud)

参数声明char c2 [] 只是语法糖char* c2.

C中的所有内容都作为值传递.有关此用途的进一步说明请使用此链接.

Eli Bendersky也有一篇很好的文章讨论同样的问题.