Overly detailed explanation:
The thing with arrays that leads to this confusion is based in the fact that arrays cannot be copied.
1 2
|
int array1[10] = {whatever};
int array2[10] = array1; // illegal, compiler error
|
Now when you pass a parameter by value, you're effectively copying it:
1 2 3 4 5 6 7 8 9 10
|
void func(int b)
{
// do something with 'b' here
}
int main()
{
int a = 5;
func(a); // effectively saying b=a; ... copying a to b
}
|
Put those two together, and you might start to see a problem. Passing a parameter creates a copy, but arrays can't be copied. So logically you'd think arrays cannot be passed as parameters.
However, the language is "accommodating" here... as it does allow you to pass a
pointer, and arrays can be implicitly cast to a pointer:
1 2 3 4
|
int array[10];
int* p1 = &array[0]; // pointer to first element
int* p2 = array; // legal, identical to above statement. 'array' is implicitly cast
// to a pointer to its first element
|
Now if you know how pointers work... you'll know that dereferencing a pointer lets you modify the variable it points to:
1 2 3 4 5
|
int bar = 5;
int* p = &bar; // p points to bar
*p = 10; // this actually modifies 'bar', not 'p'
// p still points to bar, just as it did before... but now bar is 10 instead of 5
|
This extends to functions as well:
1 2 3 4 5 6 7 8 9 10 11
|
void func(int* p)
{
*p = 10;
}
int main()
{
int var = 5;
func( &var );
// var is now 10
}
|
Following that logic, what you really have when you pass an array to a function is a pointer to the first element:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
void func(int* p)
{
// ...
}
int main()
{
int array[10];
func( array ); // 'array' is cast to a pointer, which is passed to the function
func( &array[0] ); // alternative to do the exact same thing
}
|
This is why arrays get modified when you pass them to functions, as you observed. It's because you're not passing the array, you're just passing a pointer to it.
All pretty logical so far. The real problem is that the language is
frustratingly inconsistent about the usage of []. Specifically, they have a different meaning when used in a parameter list as they do everywhere else.
1 2 3 4 5 6
|
void func( int* p ); // normal
void func( int p[] ); // IDENTICAL (wtf?) ... yes, 'p' is a pointer, not an array
void func( int p[100] ); // ALSO IDENTICAL (wtf) .. yes, 'p' is still just a pointer. Specifying
// a size of 100 does not help, and in fact is completely meaningless because you can
// still give it any pointer. The pointer does not have to point to an array of 100
// elements.
|
I don't know why the language decided to do this. My best guess is that it was a carryover from C, and it might have been a good idea in C because it allows you to be verbose. IE, for a programmer looking a function that takes
int p[]
, it's immediately clear that the intent is to pass an array to the function, not just a pointer to a single var.