为什么在C和C++中不允许将数组的值传递给函数?

问题描述 投票:9回答:6

C和C++允许将结构体和对象的值传递给函数,但不允许将数组的值传递给函数。

为什么?

c++ c arrays function parameter-passing
6个回答
18
投票

在CC++中,数组在内部是作为指向某个位置的指针来传递的,基本上,它是 值传递的。问题是,那个复制的值代表了一个内存地址,到了 同地.

在C++中,一个 vector<T> 是复制并传递给另一个函数的,顺便说一下。


11
投票

你可以按值传递一个数组,但你必须先把它包在一个结构或类中。 或者干脆使用std::vector这样的类型。

我想这个决定是为了提高效率。 人们在大多数时候都不想这么做。 这和为什么没有无符号双数的道理是一样的。 没有相关的CPU指令,所以在C++这样的语言中,你必须把效率不高的事情做得非常困难。

就像@litb提到的。"C++1x和boost都将原生数组封装到结构中,提供了std: :array和boost: :array,我一直比较喜欢,因为它允许在结构中传递和返回数组"

数组是指向存放该数组的内存和大小的指针。 注意,它和指向数组第一个元素的指针不完全一样。

大多数人认为必须将数组作为一个指针传递,并将大小作为一个单独的参数来指定,但这是不需要的。 你可以传递一个对实际数组本身的引用,同时保持它的sizeof()状态。

//Here you need the size because you have reduced 
// your array to an int* pointing to the first element.
void test1(int *x, int size)
{
  assert(sizeof(x) == 4);
}

//This function can take in an array of size 10
void test2(int (&x)[10])
{
  assert(sizeof(x) == 40);
}

//Same as test2 but by pointer
void test3(int (*x)[10])
{
  assert(sizeof(*x) == 40);
  //Note to access elements you need to do: (*x)[i]
}

有些人可能会说,一个数组的大小是不知道的。 这是不对的。

int x[10];  
assert(sizeof(x) == 40);

但是堆上的分配呢?堆上的分配不返回一个数组。 他们返回一个指向数组第一个元素的指针。 所以new不是类型安全的。 如果你确实有一个数组变量,那么你就会知道它所拥有的大小。


8
投票

EDIT:我在下面留下了最初的答案,但我相信现在大部分的价值都在评论中。我已经把它做成了社区维基,所以如果有参与后续对话的人想编辑答案以反映这些信息,请随意。

原始答案

首先,它怎么知道要分配多少栈?对于结构体和对象来说,这是固定的(我相信),但是对于数组来说,这取决于数组有多大,而这要到执行时才知道。即使每个调用者在编译时都知道,也可能有不同的调用者使用不同的数组大小)。你可以在参数声明中强制要求一个特定的数组大小,但这似乎有点奇怪。

除此之外,正如Brian所说,还有效率的问题。

你想通过这一切达到什么目的?是想确保原始数组的内容不被改变吗?


4
投票

我认为C语言中数组以指针形式传递而不是按值传递主要有3个原因。前2个原因在其他答案中已经提到了。

  • 效率
  • 因为一般情况下,数组没有大小信息(如果你包括动态分配的数组)。

然而,我认为第三个原因是由于。

  • C语言从早期的B语言和BCPL语言演变而来, 在那里,数组实际上是以数组数据的指针来实现的。

Dennis Ritchie讲述了C语言早期从BCPL和B等语言演变而来,特别是数组是如何实现的,它们是如何受到BCPL和B数组的影响,以及它们是如何和为什么不同的(而在表达式中仍然非常相似,因为数组名在表达式中衰减为指针)。


3
投票

其实我不知道 任何 的语言,支持通过 赤裸裸 数组的值。这样做并不是特别有用,而且会很快地占用调用栈。

编辑。 致下线者--如果你知道更好的方法,请告诉我们大家。


3
投票

这是那种 "只是因为 "的答案之一。C++从C语言中继承了它,并且不得不遵循它以保持兼容性。在C中这样做是为了提高效率。你很少会想在堆栈上复制一个大数组(记住,这里想想PDP-11)来传递给一个函数。

© www.soinside.com 2019 - 2024. All rights reserved.