Any particular reason why C++ treats array & 'normal' variables differently like this...?

Ok so, one thing I have noticed is that when I'm dealing with arrays, and I declare the array (array[]) and input stuff into it at the beginning of the main() function, if it then goes through a function and array[] is used as an argument, say function(array[]) and the values in array[] are changed during the function, those values remain even after the function has returned control back to the main() function. But it does not work this way with normal variables. Let me give you an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

using namespace std;

void arrayFunction(int array[]);

int main()
{
    int array[10];
    array[0] = 1;
    array[1] = 2;
    array[2] = 3;

    arrayFunction(array);

    cout << "\n\nOriginal array = " << array[0] << ", " << array[1] << ", " << array[2] << "\n";

    return 0;
}


void arrayFunction(int inputArray[])
{
    inputArray[0] = 1;
    inputArray[1] = 0;
    inputArray[2] = 3;

    cout << "inputArray = " << inputArray[0] << ", " << inputArray[1] << ", " << inputArray[2];
    return;
}


The output reads:
inputArray = 1, 0, 3

Original array = 1, 0, 3


Whereas I'd expect the original array to still be {1, 2, 3} as this is how C++ treats normal variables:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

using namespace std;

void function(int value);

int main()
{
    int x=0;
    function(x);
    cout << "\n\n" << "x = " << x;
    return 0;
}

void function(int value)
{
    value=value+1;
    cout << "\n\nvalue = " << value;
    return;
}

value = 1

x = 0


x has not changed. What is it about arrays that make C++ treat them differently?
Any info appreciated! It's bugging me. :p
Last edited on
Read about functions
http://www.cplusplus.com/doc/tutorial/functions/ and esp.
http://www.cplusplus.com/doc/tutorial/functions2/ to learn how parameters are passed to them.
Then read about pointers and esp. Pointers and arrays section in http://www.cplusplus.com/doc/tutorial/pointers/

Funny is how you find arrays' behaviour strange, while most of beginers struggle with understanding why normal variables are unchanged after being passed to a function :)
Last edited on
Thanks i'll give them a read :)

I just think it's more logical that they remain unchanged, since for example, in the case above, x is only being used as an argument for a function; nothing more, nothing less. So i don't see any reason as to why the value of x should change outside of the function :p
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.
Last edited on
My best guess is that it was a carryover from C, and it might have been a good idea in C

The strange array semantics are a carryover from C, and in C it was a carryover from B. Talk about backwards compatibility gone overboard.

Note that if you wrap a C array in a C struct, it magically becomes copyable, assignable, returnable from functions and passable by value like any other everyday variable. structs weren't a part of B, so C was able to do sensible things there. C++ went further and made that into std::array, although it's not needed all that much anyway since we have vectors.

PS: technically, syntax error when attempting to copy an array in C was not backwards compatible, it was a defensive measure against confused B programmers, for who assigning to an array meant rebasing, an operation C didn't support.. but that's ancient history anyhow

Last edited on
Topic archived. No new replies allowed.