C语言 在 C 中通过引用传递数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19646512/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:51:23  来源:igfitidea点击:

Passing an Array by reference in C

carraysfunctionreference

提问by Costagero

I'm new to C and I have a doubt.

我是 C 新手,我有疑问。

Since C functions create local copies of it's arguments, I'm wondering why the following code works as expected:

由于 C 函数创建了它的参数的本地副本,我想知道为什么下面的代码按预期工作:

void function(int array[]){

    array[0] = 4;
    array[1] = 5;
    array[2] = 6;   
}

int main(){

    int array[] = {1,2,3};

    function(array);

    printf("%d %d %d",array[0],array[1],array[2]);

    return 0;
}

With the line output being 4 5 6.

线路输出为 4 5 6。

Why does this work while the following doesn't?

为什么这有效而以下无效?

void function(int integer){

    integer = 2;
}

int main(){

    int integer = 1;

    function(integer);

    printf("%d",integer);

    return 0;
}

The output is just 1 in this case.

在这种情况下,输出仅为 1。

Short version: Why can functions modify the values of their parent variables if they are passed as array?

简短版本:如果函数作为数组传递,为什么函数可以修改其父变量的值?

Thank you all!

谢谢你们!

回答by kfsone

This is caused by the fact that arrays tend to decay into pointers.

这是由于数组倾向于衰减为指针这一事实造成的。

int a[] = { 1, 2, 3 };
int* p = a; // valid: p is now the address of a[0]
a = p;  // NOT valid.

printf("a = %p\n", a);
printf("p = %p\n", p); // prints same address as a

aand pwill print the same value.

a并且p将打印相同的值。

Contrary to what others have said, ais nota pointer, it can simply decay to one. http://c-faq.com/aryptr/aryptrequiv.html

相反的是其他人所说的,a不是一个指针,它可以简单地衰减到一个。http://c-faq.com/aryptr/aryptrequiv.html

In your first function()what gets passed is the address of the array's first element, and the function body dereferences that. Infact, the compiler is treating the function prototype as this:

在你的第一个function()传递的是数组的第一个元素的地址,函数体取消引用它。事实上,编译器将函数原型视为这样:

void function(int* array /*you wrote int array[]*/){
    array[0] = 4;
    array[1] = 5;
    array[2] = 6;   
}

function(&array[0]);

This has to happen because you said "array of unknown size" (int array[]). The compiler could not guarantee to deduce the amount of stack required to pass by value, so it decays to a pointer.

这必须发生,因为您说的是“未知大小的数组”(int array[])。编译器无法保证推导出按值传递所需的堆栈量,因此它会衰减为指针。

---- Edit ----

- - 编辑 - -

Lets combine both your examples and use more distinctive names to make things clearer.

让我们结合您的示例并使用更独特的名称使事情更清楚。

#include <stdio.h>

void func1(int dynArray[]) {
    printf("func1: dynArray = %p, &dynArray[0] = %p, dynArray[0] = %d\n",
             dynArray, &dynArray[0], dynArray[0]);
}

void func2(int* intPtr) {
    printf("func2: intPtr = %p, &intPtr[0] = %p, intPtr[0] = %d\n",
             intPtr, &intPtr[0], intPtr[0]);
}

void func3(int intVal) {
    printf("func3: intVal = %d, &intValue = %p\n",
             intVal, &intVal);
}

int main() {
    int mainArray[3] = { 1, 2, 3 };
    int mainInt = 10;

    printf("mainArray = %p, &mainArray[0] = %p, mainArray[0] = %d\n",
             mainArray, &mainArray, mainArray[0]);
    func1(mainArray);
    func2(mainArray);

    printf("mainInt = %d, &mainInt = %p\n",
             mainInt, &mainInt);
    func3(mainInt);

    return 0;
}

Live demo at ideone: http://ideone.com/P8C1f4

ideone 现场演示:http://ideone.com/P8C1f4

mainArray = 0xbf806ad4, &mainArray[0] = 0xbf806ad4, mainArray[0] = 1
func1: dynArray = 0xbf806ad4, &dynArray[0] = 0xbf806ad4, dynArray[0] = 1
func2: intPtr = 0xbf806ad4, &intPtr[0] = 0xbf806ad4, intPtr[0] = 1

mainInt = 10, &mainInt = 0xbf806acc
func3: intVal = 10, &intValue = 0xbf806ad0

In func1and func2"dynArray" and "intPtr" are local variables, but they are pointer variables into which they receive the address of "mainArray" from main.

Infunc1func2"dynArray" 和 "intPtr" 是局部变量,但它们是指针变量,它们从 main 接收 "mainArray" 的地址。

This behavior is specific to arrays. If you were to put the array inside a struct, then you would be able to pass it by value.

此行为特定于数组。如果要将数组放入结构中,则可以按值传递它。

回答by StarkOverflow

An array passed to a function is converted to a pointer. When you pass a pointer as argument to a function, you simply give the address of the variable in the memory. So when you modify the value of the cell of the array, you edit the value under the address given to the function.

传递给函数的数组被转换为指针。当您将指针作为参数传递给函数时,您只需给出变量在内存中的地址。因此,当您修改数组单元格的值时,您可以编辑提供给函数的地址下的值。

When you pass a simple integer to a function, the integer is copied in the stack, when you modify the integer within the function, you modify the copy of the integer, not the original.

当您将一个简单的整数传递给函数时,该整数被复制到堆栈中,当您在函数内修改该整数时,您修改的是该整数的副本,而不是原始整数。

Reminder of the different kinds of memory in C

提醒 C 中不同类型的内存

In C, we can use three types of memory :

在 C 中,我们可以使用三种类型的内存:

  • the stack, used for local variables and functions calls: when we create a variable in main(), we use the stack to store the variable, and when a function is called, the parameters given to the method are register in the stack. When we exit a function, we "pop" these parameters to return to the original state, with the used variable before the call of the function. (anecdote: a stackoverflow is when we hack the stack to use previous variables in a function without passing it as parameters)
  • the heap which corresponds to the dynamicly allocated memory: when we need large amount of data, we use this heap because the stack is limited to a few megabytes.
  • the code where the program instructions are stored
  • 栈,用于局部变量和函数调用:当我们在main()中创建一个变量时,我们使用栈来存储该变量,当一个函数被调用时,给该方法的参数被注册到栈中。当我们退出函数时,我们“弹出”这些参数以返回到原始状态,以及调用函数之前使用的变量。(轶事:stackoverflow 是当我们破解堆栈以在函数中使用先前的变量而不将其作为参数传递时)
  • 动态分配内存对应的堆:当我们需要大量数据时,我们使用这个堆,因为堆栈被限制在几兆字节。
  • 存储程序指令的代码

In the case of this array passed by a function, which is a pointer (address to an other variable), it is stored in the stack, when we call the function, we copy the pointer in the stack.

在这个数组由函数传递的情况下,它是一个指针(指向另一个变量的地址),它存储在堆栈中,当我们调用函数时,我们将指针复制到堆栈中。

In the case of the integer, it is also stored in the stack, when we call the function, we copy the integer.

在整数的情况下,它也存储在堆栈中,当我们调用函数时,我们复制整数。

If we want to modify the integer, we can pass the address of the integer to modify the value under the pointer, like this:

如果我们要修改整数,我们可以通过整数的地址来修改指针下的值,像这样:

void function(int *integer)
{
    *integer = 2;
}

int main()
{
    int integer = 1;
    function(&integer);

    printf("%d", integer);

    return 0;
}

回答by Mazzy

There is a difference between 'pass by reference' and 'pass by value'

“按引用传递”和“按值传递”之间存在差异

Pass by reference leads to a location in the memory where pass by value passes the value directly, an array variable is always an refference, so it points to a location in the memory. Integers will pass by value by default

引用传递导致内存中的某个位置,值传递直接传递值,数组变量始终是引用,因此它指向内存中的某个位置。默认情况下,整数将按值传递

回答by Mazzy

In the first code, you are passing the address of the array pointing to the top element in the array. So, when you modify the value in the function and return to the main function you are still accessing the same array which is in the same address. This is called pass by reference.

在第一个代码中,您传递指向数组顶部元素的数组地址。因此,当您修改函数中的值并返回主函数时,您仍在访问位于同一地址中的同一个数组。这称为通过引用传递。

However, in the second case, the value of the integer is copied from the main function to the called function. In other words, the two integers are in different address in the memory. So modifying one does not modify the other.

但是,在第二种情况下,整数的值从主函数复制到被调用函数。换句话说,这两个整数在内存中的地址不同。所以修改一个不会修改另一个。

回答by Rami

The array name is a pointer to the first element in the array. In the first code sample you have passed a pointer to the memory location containing the first array element. In the second code sample you have passed an integer by value so it has nothing to do with the local variable named "integer"

数组名称是指向数组中第一个元素的指针。在第一个代码示例中,您传递了一个指向包含第一个数组元素的内存位置的指针。在第二个代码示例中,您通过值传递了一个整数,因此它与名为“integer”的局部变量无关

check that link

检查该链接

Pass by reference and pass by value

按引用传递和按值传递

Pass by Reference / Value in C++

在 C++ 中通过引用/值传递