为什么C或C ++不允许通过值传递数组来起作用

时间:2022-03-21 22:35:34

C and C++ allows passing of structure and objects by value to function, although prevents passing arrays by values, why?

C和C ++允许按值将结构和对象传递给函数,虽然可以防止按值传递数组,为什么呢?

6 个解决方案

#1


18  

In C/C++, internally, an array is passed as a pointer to some location, and basically, it is passed by value. The thing is, that copied value represents a memory address to the same location.

在C / C ++中,在内部,数组作为指向某个位置的指针传递,基本上,它是通过值传递的。问题是,复制的值表示同一位置的内存地址。

In C++, a vector<T> is copied and passed to another function, by the way.

在C ++中,向量 被复制并传递给另一个函数。

#2


11  

You can pass an array by value, but you have to first wrap it in a struct or class. Or simply use a type like std::vector.

您可以按值传递数组,但必须先将其包装在结构或类中。或者只是使用类似std :: vector的类型。

I think the decision was for the sake of efficiency. One wouldn't want to do this most of the time. It's the same reasoning as why there are no unsigned doubles. There is no associated CPU instruction, so you have to make what's not efficient very hard to do in a language like C++.

我认为这个决定是出于效率的考虑。人们不希望大部分时间都这样做。这与为什么没有无符号双打的原因相同。没有相关的CPU指令,所以你必须用C ++这样的语言来做很难的事情。

As @litb mentioned: "C++1x and boost both have wrapped native arrays into structs providing std::array and boost::array which i would always prefer because it allows passing and returning of arrays within structs"

正如@litb所说:“C ++ 1x和boost都将原生数组包装成结构提供了std :: array和boost :: array,我总是喜欢它,因为它允许在结构中传递和返回数组”

An array is a pointer to the memory that holds that array and the size. Note it is not the exact same as a pointer to the first element of the array.

数组是指向保存该数组和大小的内存的指针。请注意,它与指向数组第一个元素的指针不完全相同。

Most people think that you have to pass an array as a pointer and specify the size as a separate parameter, but this is not needed. You can pass a reference to the actual array itself while maintaining it's sizeof() status.

大多数人认为您必须将数组作为指针传递并将大小指定为单独的参数,但这不是必需的。您可以在保持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]
}

Some people may say that the size of an array is not known. This is not true.

有些人可能会说数组的大小未知。这不是真的。

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

But what about allocations on the heap? Allocations on the heap do not return an array. They return a pointer to the first element of an array. So new is not type safe. If you do indeed have an array variable, then you will know the size of what it holds.

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

#3


8  

EDIT: I've left the original answer below, but I believe most of the value is now in the comments. I've made it community wiki, so if anyone involved in the subsequent conversation wants to edit the answer to reflect that information, feel free.

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

Original answer

For one thing, how would it know how much stack to allocate? That's fixed for structures and objects (I believe) but with an array it would depend on how big the array is, which isn't known until execution time. (Even if each caller knew at compile-time, there could be different callers with different array sizes.) You could force a particular array size in the parameter declaration, but that seems a bit strange.

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

Beyond that, as Brian says there's the matter of efficiency.

除此之外,正如布莱恩所说,这就是效率问题。

What would you want to achieve through all of this? Is it a matter of wanting to make sure that the contents of the original array aren't changed?

你希望通过这一切实现什么目标?是否需要确保原始数组的内容不会更改?

#4


4  

I think that there 3 main reasons why arrays are passed as pointers in C instead of by value. The first 2 are mentioned in other answers:

我认为有三个主要原因导致数组作为指针传递给C而不是值。其他答案中提到了前两个:

  • efficiency
  • because there's no size information for arrays in general (if you include dynamically allocated arrays)
  • 因为一般没有数组的大小信息(如果包含动态分配的数组)

However, I think a third reason is due to:

但是,我认为第三个原因是由于:

  • the evolution of C from earlier languages like B and BCPL, where arrays were actually implemented as a pointer to the array data
  • C和早期语言(如B和BCPL)中C的演变,其中数组实际上是作为指向数组数据的指针实现的

Dennis Ritchie talks about the early evolution of C from languages like BCPL and B and in particular how arrays are implemented and how they were influenced by BCPL and B arrays and how and why they are different (while remaining very similar in expressions because array names decay into pointers in expressions).

Dennis Ritchie谈到了C语言和B语言等C语言的早期演变,特别是如何实现数组以及它们如何受BCPL和B数组的影响以及它们如何以及为何与它们不同(尽管数组中的数组仍然非常相似,因为数组名称会衰减到表达式中的指针)。

#5


3  

I'm not actually aware of any languages that support passing naked arrays by value. To do so would not be particularly useful and would quickly chomp up the call stack.

我实际上并不知道任何支持按值传递裸数组的语言。这样做不会特别有用,并且很快会扼杀调用堆栈。

Edit: To downvoters - if you know better, please let us all know.

编辑:对于downvoters - 如果你知道的更好,请让我们都知道。

#6


3  

This is one of those "just because" answers. C++ inherited it from C, and had to follow it to keep compatibility. It was done that way in C for efficiency. You would rarely want to make a copy of a large array (remember, think PDP-11 here) on the stack to pass it to a function.

这是“仅仅因为”答案之一。 C ++从C继承它,并且必须遵循它以保持兼容性。这样做是为了提高效率。您很少想要在堆栈上复制一个大型数组(请记住,在这里考虑PDP-11)以将其传递给函数。

#1


18  

In C/C++, internally, an array is passed as a pointer to some location, and basically, it is passed by value. The thing is, that copied value represents a memory address to the same location.

在C / C ++中,在内部,数组作为指向某个位置的指针传递,基本上,它是通过值传递的。问题是,复制的值表示同一位置的内存地址。

In C++, a vector<T> is copied and passed to another function, by the way.

在C ++中,向量 被复制并传递给另一个函数。

#2


11  

You can pass an array by value, but you have to first wrap it in a struct or class. Or simply use a type like std::vector.

您可以按值传递数组,但必须先将其包装在结构或类中。或者只是使用类似std :: vector的类型。

I think the decision was for the sake of efficiency. One wouldn't want to do this most of the time. It's the same reasoning as why there are no unsigned doubles. There is no associated CPU instruction, so you have to make what's not efficient very hard to do in a language like C++.

我认为这个决定是出于效率的考虑。人们不希望大部分时间都这样做。这与为什么没有无符号双打的原因相同。没有相关的CPU指令,所以你必须用C ++这样的语言来做很难的事情。

As @litb mentioned: "C++1x and boost both have wrapped native arrays into structs providing std::array and boost::array which i would always prefer because it allows passing and returning of arrays within structs"

正如@litb所说:“C ++ 1x和boost都将原生数组包装成结构提供了std :: array和boost :: array,我总是喜欢它,因为它允许在结构中传递和返回数组”

An array is a pointer to the memory that holds that array and the size. Note it is not the exact same as a pointer to the first element of the array.

数组是指向保存该数组和大小的内存的指针。请注意,它与指向数组第一个元素的指针不完全相同。

Most people think that you have to pass an array as a pointer and specify the size as a separate parameter, but this is not needed. You can pass a reference to the actual array itself while maintaining it's sizeof() status.

大多数人认为您必须将数组作为指针传递并将大小指定为单独的参数,但这不是必需的。您可以在保持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]
}

Some people may say that the size of an array is not known. This is not true.

有些人可能会说数组的大小未知。这不是真的。

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

But what about allocations on the heap? Allocations on the heap do not return an array. They return a pointer to the first element of an array. So new is not type safe. If you do indeed have an array variable, then you will know the size of what it holds.

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

#3


8  

EDIT: I've left the original answer below, but I believe most of the value is now in the comments. I've made it community wiki, so if anyone involved in the subsequent conversation wants to edit the answer to reflect that information, feel free.

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

Original answer

For one thing, how would it know how much stack to allocate? That's fixed for structures and objects (I believe) but with an array it would depend on how big the array is, which isn't known until execution time. (Even if each caller knew at compile-time, there could be different callers with different array sizes.) You could force a particular array size in the parameter declaration, but that seems a bit strange.

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

Beyond that, as Brian says there's the matter of efficiency.

除此之外,正如布莱恩所说,这就是效率问题。

What would you want to achieve through all of this? Is it a matter of wanting to make sure that the contents of the original array aren't changed?

你希望通过这一切实现什么目标?是否需要确保原始数组的内容不会更改?

#4


4  

I think that there 3 main reasons why arrays are passed as pointers in C instead of by value. The first 2 are mentioned in other answers:

我认为有三个主要原因导致数组作为指针传递给C而不是值。其他答案中提到了前两个:

  • efficiency
  • because there's no size information for arrays in general (if you include dynamically allocated arrays)
  • 因为一般没有数组的大小信息(如果包含动态分配的数组)

However, I think a third reason is due to:

但是,我认为第三个原因是由于:

  • the evolution of C from earlier languages like B and BCPL, where arrays were actually implemented as a pointer to the array data
  • C和早期语言(如B和BCPL)中C的演变,其中数组实际上是作为指向数组数据的指针实现的

Dennis Ritchie talks about the early evolution of C from languages like BCPL and B and in particular how arrays are implemented and how they were influenced by BCPL and B arrays and how and why they are different (while remaining very similar in expressions because array names decay into pointers in expressions).

Dennis Ritchie谈到了C语言和B语言等C语言的早期演变,特别是如何实现数组以及它们如何受BCPL和B数组的影响以及它们如何以及为何与它们不同(尽管数组中的数组仍然非常相似,因为数组名称会衰减到表达式中的指针)。

#5


3  

I'm not actually aware of any languages that support passing naked arrays by value. To do so would not be particularly useful and would quickly chomp up the call stack.

我实际上并不知道任何支持按值传递裸数组的语言。这样做不会特别有用,并且很快会扼杀调用堆栈。

Edit: To downvoters - if you know better, please let us all know.

编辑:对于downvoters - 如果你知道的更好,请让我们都知道。

#6


3  

This is one of those "just because" answers. C++ inherited it from C, and had to follow it to keep compatibility. It was done that way in C for efficiency. You would rarely want to make a copy of a large array (remember, think PDP-11 here) on the stack to pass it to a function.

这是“仅仅因为”答案之一。 C ++从C继承它,并且必须遵循它以保持兼容性。这样做是为了提高效率。您很少想要在堆栈上复制一个大型数组(请记住,在这里考虑PDP-11)以将其传递给函数。