0

My question is pretty straightfoward: why can I assign a value that goes out of bounds to an array like this, but not with the {} operator:

int arr[2];

arr[2] = 2;

for(int num{0}; num < 3; num++)
    cout << arr[num] << endl;

But when I do this I get an error right from the start:

int arr[2] {1,2,3};

Now I know that assigning a value beyond the scope of the array may cause an undefinied behavior, as this questions has clarified to me:

Accessing an array out of bounds gives no error, why?

But why can't I go beyond the arrays' limit in the second case? Even though it is wrong - And I don't intend to do it - I'd like to know the difference in these cases.

Isaias
  • 43
  • 1
  • 5
  • 3
    Because one can be verified at compile time, while the other (in general) can’t be. To be fair, compilers *could* add an error for your particular case, since that’s clearly diagnosable at compile-time as well. They probably chose not to because it’s a relatively rare scenario and not worth the added maintenance burden in the compiler (though that’s debatable). – Konrad Rudolph Feb 03 '22 at 13:30
  • 1
    Note that the second use case is an [initialization](https://en.cppreference.com/w/c/language/array_initialization#Initialization_from_brace-enclosed_lists), where the `[2]` is the *size*, while in the first snippet `[2]` is a call to the array subscript operator with *index* 2. – Bob__ Feb 03 '22 at 13:43
  • 1
    @KonradRudolph clang does produce a `warning: array index 2 is past the end of the array (which contains 2 elements) [-Warray-bounds]`. – Ruslan Feb 03 '22 at 14:17
  • 1
    *why can I assign a value that goes out of bounds to an array like this* You can't do that, it's **undefined behavior**. What you probably meant is "why doesn't the compiler error on this", and that's because in general the compiler does not catch that error (although this particular example, compilers could detect that mistake and warn about it, but it is not required by the standard) — it is the programmers responsibility to not let that happen. C++ is not a nanny language; it gives you enough rope to shoot yourself in the foot. – Eljay Feb 03 '22 at 14:35

1 Answers1

2

Both cases are completly different. The first one is array element assignement. The second is array initialization. The rules state that it is an error if you provide more initializers that the array can hold. The rules state also, that element access behind the array end is not an error but undefined behaviour. In other languages, there is bound checking at runtime for array access, but not in C++. So the reason it behaves like it does, is that the C++ standard commitee decided so.

You could of course ask why the C++ standard commitee decided so. I think the answer is, that C++ tries to be as backward compatible as possible and the rules for array element access have always been that way.

Also the initialization can be evaluated and checked at compile time, whereas the element access happens during runtime and the compiler cannot foresee if there is actually an access behind the end of the array.

Jakob Stark
  • 3,346
  • 6
  • 22