C语言 按值将数组传递给函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4774456/
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:35:27  来源:igfitidea点击:

Pass an array to a function by value

carraysfunctionpass-by-referencepass-by-value

提问by Zuzu

Below is a snippet from the book C Programming Just the FAQs. Isn't this wrong as Arrays can never be passed by value?

下面是C Programming Just the FAQs一书中的一个片段。这不是错误,因为数组永远不能按值传递吗?

VIII.6: How can you pass an array to a function by value?

Answer:An array can be passed to a function by value by declaring in the called function the array name with square brackets ([and ]) attached to the end. When calling the function, simply pass the address of the array (that is, the array's name) to the called function. For instance, the following program passes the array x[]to the function named byval_func()by value:

The int[]parameter tells the compiler that the byval_func()function will take one argument—an array of integers. When the byval_func()function is called, you pass the address of the array to byval_func():

byval_func(x);

Because the array is being passed by value, an exact copy of the array is made and placed on the stack. The called function then receives this copy of the array and can print it. Because the array passed to byval_func()is a copy of the original array, modifying the array within the byval_func()function has no effect on the original array.

VIII.6: 如何将数组按值传递给函数?

答案:可以通过在被调用函数中声明数组名称[]在末尾附加方括号 (和)将数组按值传递给函数。调用函数时,只需将数组的地址(即数组的名称)传递给被调用函数即可。例如,以下程序将数组传递给以 值x[]命名 byval_func()的函数:

int[]参数告诉编译器该byval_func()函数将采用一个参数——一个整数数组。当 byval_func()函数被调用时,你将数组的地址传递给 byval_func()

byval_func(x);

因为数组是按值传递的,所以制作了数组的精确副本并将其放置在堆栈中。然后被调用的函数接收数组的这个副本并可以打印它。因为传递给的数组 byval_func()是原始数组的副本,所以在byval_func()函数内修改数组对原始数组没有影响。

回答by Péter T?r?k

Because the array is being passed by value, an exact copy of the array is made and placed on the stack.

因为数组是按值传递的,所以制作了数组的精确副本并将其放置在堆栈中。

This is incorrect: the array itself is not being copied, only a copy of the pointer to its address is passed to the callee (placed on the stack). (Regardless of whether you declare the parameter as int[]or int*, it decays into a pointer.) This allows you to modify the contents of the array from within the called function. Thus, this

这是不正确的:数组本身没有被复制,只有指向其地址的指针的副本传递给被调用者(放置在堆栈上)。(无论您是否将参数声明为int[]int*,它都会衰减为一个指针。)这允许您从被调用的函数中修改数组的内容。因此,这

Because the array passed to byval_func()is a copy of the original array, modifying the array within the byval_func()function has no effect on the original array.

因为传递给的数组byval_func()是原始数组的副本,所以在byval_func()函数内修改数组对原始数组没有影响。

is plain wrong (kudos to @Jonathan Leffler for his comment below). However, reassigning the pointer inside the function will not change the pointer to the original array outside the function.

完全错误(感谢@Jonathan Leffler 在下面发表评论)。但是,在函数内部重新分配指针不会改变指向函数外部原始数组的指针。

回答by Lundin

Burn that book. If you want a real C FAQ that wasn't written by a beginner programmer, use this one: http://c-faq.com/aryptr/index.html.

烧掉那本书。如果您想要一个不是由初学者程序员编写的真正的 C 常见问题解答,请使用这个:http: //c-faq.com/aryptr/index.html

Syntax-wise, strictly speaking you cannotpass an array by value in C.

语法方面,严格来说,你不能在 C 中按值传递数组。

void func (int* x); /* this is a pointer */

void func (int x[]); /* this is a pointer */

void func (int x[10]); /* this is a pointer */

However, for the record there is a dirty trick in C that does allow you to pass an array by value in C. Don't try this at home! Because despite this trick, there is still never a reason to pass an array by value.

但是,为了记录,C 中有一个肮脏的技巧,它允许您在 C 中按值传递数组。不要在家里尝试这个!因为尽管有这个技巧,仍然没有理由按值传递数组。

typedef struct
{
  int my_array[10];
} Array_by_val;

void func (Array_by_val x);

回答by RobertS supports Monica Cellio

Isn't this wrong as arrays can never be passed by value?

这不是错误的,因为数组永远不能按值传递吗?

Exactly. You cannot pass an array by value in C.

确切地。您不能在 C 中按值传递数组。

I took a look at the quoted part of the book and the source of this confusion or mistake is pretty fast found.

我看了一下书中引用的部分,很快就找到了这种混淆或错误的根源。

The author did not know about that *iis equivalent to i[]when provided as a parameter to a function. The latter form was invented to explicitly illustrate the reader of the code, that ipoints to an array, which is a great source of confusion, as well-shown by this question.

作者不知道这*i相当于i[]当作为参数提供给函数时。发明后一种形式是为了明确说明代码的读者,它i指向一个数组,这是一个很大的混淆源,正如这个问题所示。

What I think is funny, that the author of the particular part of the book or at least one of the other parts (because the book has 5authors in total) or one of the 7proofreaders did not mentioned at least the sentence:

我认为有趣的是,本书特定部分的作者或至少其他部分之一(因为这本书共有5 个作者)或7 个校对者之一至少没有提到这句话:

"When the byval_func()function is called, you pass the addressof the array to byval_func():"

"byval_func()函数被调用时,你将数组的地址传递给byval_func()"

With at least that, they should had noticed that there is a conflict. Since you passing an address, it is only an address. There is nothing magically happen which turns an address into a whole new array.

至少,他们应该注意到存在冲突。由于您传递了地址,因此它只是一个地址。没有什么神奇的事情可以将地址变成一个全新的数组。



But back to the question itself:

但回到问题本身:

You can not pass an array as it is by value in C, as you already seem to know yourself. But you can do three (there might be more, but that is my acutal status of it) things, which might be an alternative depending on the unique case, so let′s start.

您不能在 C 中按值传递数组,因为您似乎已经了解自己。但是你可以做三件事(可能有更多,但这是我对它的实际状态),这可能是根据独特情况的替代方案,所以让我们开始吧。

  1. Encapsulate an array in a structure (as mentioned by other answers):
  1. 将数组封装在结构中(如其他答案所述):
#include <stdio.h>

struct a_s {
   int a[20];
};

void foo (struct a_s a)
{
   size_t length = sizeof a.a / sizeof *a.a;

   for(size_t i = 0; i < length; i++)
   {
       printf("%d\n",a.a[i]);
   }
}

int main()
{
   struct a_s array;

   size_t length = sizeof array.a / sizeof *array.a;

   for(size_t i = 0; i < length; i++)
   {
       array.a[i] = 15;
   } 

   foo(array);
}
  1. Pass by pointer but also add a parameter for determine the size of the array. In the called function there is made a new array with that size information and assigned with the values from the array in the caller:
  1. 传递指针还要添加一个参数来确定数组的大小。在被调用的函数中,创建了一个具有该大小信息的新数组,并分配了调用者中数组中的值:
#include <stdio.h>

void foo (int *array, size_t length)
{
   int b[length];

   for(size_t i = 0; i < length; i++)
   {
       b[i] = array[i];
       printf("%d\n",b[i]);
   }
}

int main()
{
   int a[10] = {0,1,2,3,4,5,6,7,8,9};

   foo(a,(sizeof a / sizeof *a));
}
  1. Avoid to define local arrays and just use one array with global scope:
  1. 避免定义局部数组而只使用一个具有全局作用域的数组:
#include <stdio.h>

int a[10];
size_t length = sizeof a / sizeof *a;

void foo (void)
{
   for(size_t i = 0; i < length; i++)
   {
       printf("%d\n",a[i]);
   }
}

int main()
{   
   for(size_t i = 0; i < length; i++)
   {
       a[i] = 25;
   } 

   foo();
}

回答by Rongkai Xu

In C and C++ it is NOT possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address. In practice this has almost the same effect and it is a much faster and more efficient operation.

在 C 和 C++ 中,不可能将完整的内存块按值作为参数传递给函数,但我们可以传递它的地址。在实践中,这几乎具有相同的效果,而且操作速度更快、效率更高。

To be safe, you can pass the array size or put const qualifier before the pointer to make sure the callee won't change it.

为安全起见,您可以传递数组大小或在指针之前放置 const 限定符以确保被调用者不会更改它。

回答by P__J__

Yuo can work it around by wrapping the array into the struct

Yuo 可以通过将数组包装到结构中来解决它

#include <stdint.h>
#include <stdio.h>

struct wrap
{
    int x[1000];
};

struct wrap foo(struct wrap x)
{
    struct wrap y;

    for(int index = 0; index < 1000; index ++)
        y.x[index] = x.x[index] * x.x[index];
    return y;
}

int main ()
{
    struct wrap y;

    for(int index = 0; index < 1000; index ++)
        y.x[index] = rand();
    y = foo(y);
    for(int index = 0; index < 1000; index ++)
    {
        printf("%d %s", y.x[index], !(index % 30) ? "\n" : "");
    }


}

回答by Varun Chhangani

#include<stdio.h>
void  fun(int a[],int n);
int main()
{
    int a[5]={1,2,3,4,5};
    fun(a,5);
}
void  fun(int a[],int n)
{
    int i;
    for(i=0;i<=n-1;i++)
        printf("value=%d\n",a[i]);
}

By this method we can pass the array by value, but actually the array is accessing through the its base address which actually copying in the stack.

通过这种方法,我们可以按值传递数组,但实际上数组是通过其实际复制到堆栈中的基地址来访问的。