按值将数组传递给函数

发布于 2024-10-13 21:51:30 字数 733 浏览 8 评论 0原文

以下是《C 编程常见问题解答》一书的片段。这不是错误的吗,因为数组永远不能按值传递?

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

答案:通过在中声明,可以将数组按值传递给函数 被调用的函数 数组名称 带方括号([]) 附在最后。当拨打电话时 函数,只需传递地址 数组(即数组的名称) 到被调用的函数。例如, 以下程序传递数组 x[] 到名为的函数 byval_func() 按值:

int[] 参数告诉 编译器认为byval_func() 函数将接受一个参数——一个 整数数组。当 调用 byval_func() 函数,您 将数组的地址传递给 byval_func():

byval_func(x);

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

幽蝶幻影 2024-10-20 21:51:30

由于数组是按值传递的,因此会创建该数组的精确副本并将其放置在堆栈上。

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

由于传递给 byval_func() 的数组是原始数组的副本,因此在 byval_func() 函数中修改数组对原始数组没有影响。

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

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

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.

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.

挽袖吟 2024-10-20 21:51:30

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

从语法角度来说,严格来说,您不能在 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 */

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

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

void func (Array_by_val x);

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.

Syntax-wise, strictly speaking you cannot pass an array by value in 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.

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

void func (Array_by_val x);
友谊不毕业 2024-10-20 21:51:30

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

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

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

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

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

调用 byval_func() 函数时,将数组的地址传递给 byval_func():< /em>"


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


但回到问题本身:

你不能像 C 中的值那样传递数组,因为你似乎已经了解自己了。但是你可以做三件事(可能还有更多,但这是我的实际状态),这可能是一种替代方案,具体取决于独特的情况,所以让我们开始吧。

  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. 通过指针传递,但还添加一个参数来确定数组的大小。在被调用函数中,会创建一个具有该大小信息的新数组,并分配调用者中数组中的值:
#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. 避免定义本地数组,而只使用一个具有全局作用域的数组:
#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();
}

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

Exactly. You cannot pass an array by value in 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 *i is 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 i points to an array, which is a great source of confusion, as well-shown by this question.

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 5 authors in total) or one of the 7 proofreaders did not mentioned at least the sentence:

"When the byval_func() function is called, you pass the address of the array to 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.

  1. Encapsulate an array in a structure (as mentioned by other answers):
#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:
#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:
#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();
}
眉目亦如画i 2024-10-20 21:51:30

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

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

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.

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.

你如我软肋 2024-10-20 21:51:30

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" : "");
    }


}

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

#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" : "");
    }


}
一袭水袖舞倾城 2024-10-20 21:51:30
#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]);
}

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

#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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文