C and C++ allows passing of structure and objects by value to function, although prevents passing arrays by values, why?
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.
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++.
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"
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.
//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.
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?
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.
In C++, a vector<T>
is copied and passed to another function, by the way.
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.
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.
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:
- 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
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).