13

I was given a homework question that really confuses me. The question is:

In C++ the equality test == may be applied to arrays, but the assignment operator = cannot be applied to arrays. Explain why.

This confuses me, because my understanding is that the == operator would just compare the addresses of the first two elements (which if two arrays were in fact held in separate memory locations, of course would be different). And the = operator, when used like array1 = array2; would just cause array1 to point to the same memory location as array2 does.

What am I missing here? It seems as though either operator can be used, but neither would produce the results typically intended by those operators.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Adam S
  • 8,945
  • 17
  • 67
  • 103
  • It's interesting to think that == works for an array while it doesn't for an std::vector! – Tugrul Ates Mar 17 '11 at 21:59
  • 2
    @junjanes: `==` does indeed work for `std::vector`. For arrays `==` tests for identity equality (are the left and right hand sides the same array), since `==` for arrays really compares the addresses of the initial elements of the arrays. This is not usually what you want when you want to test whether arrays are "equal." For `vector`, the `==` does what you would expect for an equality comparison: it tests whether all of the elements in one `vector` compares equal to the corresponding elements in the other `vector`. – James McNellis Mar 17 '11 at 22:03
  • 3
    It's actually quite hard to explain why arrays aren't assignable. "Because the standard says so", obviously, but they easily could have been. The reason for the decision is quite old, and AFAIK is something like: during the initial design of C there was a serious possibility of making array names actually *be* pointers, initialized pointing to automatic storage. It would then be potentially confusing whether assignment should copy the array or reseat the pointer, so rather than do either it was ruled out, and the decision to rule it out stuck. Is this C++ homework, or history homework? ;-) – Steve Jessop Mar 17 '11 at 22:16
  • Thinking about it, perhaps it stuck because making arrays assignable in C would require an additional rule about arrays not decaying to pointers when the assignment was done, and that rule perhaps would have been a fair bit more complex than the existing, very simple situations in which decay doesn't happen. The C89 standard was reasonably terse. – Steve Jessop Mar 17 '11 at 22:19
  • @Steve Jessop: Perhaps also because arrays have some metadata attached, such as array size. Given `char a[5]; char b[4]; a = b;` what happens? What is `sizeof(a)`? Should the assignment be disallowed? The easiest way to deal with the questions was to make sure they never came up. – David Thornley Mar 18 '11 at 13:33
  • @David: Perhaps, I suppose VLAs do throw a spanner in the works, I was really only thinking about C89/C++ arrays. For those, the answer is straightforward, isn't it? `a=b` should be disallowed, because `int[5]` and `int[4]` are incompatible types. Arrays are already *indirectly* assignable in C, as struct members, and I don't think it's at all beyond human wit to extend the struct assignment rules to arrays. But people would still complain that they can't be passed by value, and that would be a bit harder to define, so at this late stage I don't think there's much point trying to fix the mess. – Steve Jessop Mar 18 '11 at 14:39

1 Answers1

20

my understanding is that the == operator would just compare the addresses of the first two elements

This is correct: if you compare two arrays using ==, it will compare the addresses of the arrays, so it will only yield true if you compare an array with itself (or with a pointer to an element of the same type). See the description below for why.

the = operator, when used like array1 = array2; would just cause array1 to point to the same memory location as array2 does.

This is not correct because an array is not a pointer. array1 can't point to the same memory location as array2 because array1 isn't a pointer, it's an array of elements.

An array is a sequence of elements. In most contexts, the name of an array is implicitly converted to a pointer to its initial element. This is why you can do things like:

void f(int*);

int data[10];
int* p = data; // this is the same as 'int* p = &data[0];'
f(data);       // this is the same as 'f(&data[0]);'

array1 = array2; won't work because arrays are not assignable (mostly for historical reasons; I've never heard a convincing technical reason why it isn't allowed: it was never allowed in C, and C has been around for decades. There's some discussion of this in the comments and answers to Why does C support memberwise assignment of arrays within structs but not generally?).

The following program will not compile:

int main() {
    int a[10], b[10];
    a = b;
}

For an "assignable" array, you can use the array container-like class found in Boost (boost::array), C++ TR1 (std::tr1::array), or C++0x (std::array). It is actually a class that contains an array; it can be copied and it provides many of the benefits of the Standard Library containers plus the performance characteristics of an array and the ability to use its data as an array when you need to.

Community
  • 1
  • 1
James McNellis
  • 348,265
  • 75
  • 913
  • 977