0

I have a piece of code:

#include <iostream>
using namespace std;

int main(){

    char a[5][5] = {{'x','y','z','a','v'},{'d','g','h','v','x'}};

    for(int i=0; i<2; i++){
        for(int j = 0; j<6; j++)
        {
            cout << a[i][j];
        }
    }

    return 0;

}

As you can see the first and second dimensions are or size 5 elements each. With the double for loop's I am just printing what is initialized for variable a.

The size of int "j", as it increases the output changes dramatically.

Why is this happen?

Does pointer is the solution to this? If yes how? If no what can we do to avoid run time errors caused by this incorrect access?

  • 1
    Think about `5` and `6` carefully. – Kerrek SB Apr 29 '17 at 01:00
  • @KerrekSB 6 is not there, but still if I access it: I can able to access, there wont be any error and the output is xyzavddghvx. Why that extra d? – 14yearoldprogrammer Apr 29 '17 at 01:02
  • Change `'d'` in the array into, say, `'W'` and see what happens. – bipll Apr 29 '17 at 01:04
  • C(++) arrays are but areas in memory with some content. They are limited in size but they don't provide any special contracts on how you use them, you'll have to watch for your array operations correctness on your own. – bipll Apr 29 '17 at 01:06
  • You're accessing the same memory location twice, a[0][5], and a[1][0] contain the same data as your array has been stored contiguously. – nitronoid Apr 29 '17 at 01:07
  • If you access `[5]` when the array only has `[0]` through `[4]`, you get *undefined behaviour*. You have to write programs that don't access past the end of arrays. You can use [`vector::at()`](http://en.cppreference.com/w/cpp/container/vector/at) instead to have the compiler generate code that checks for invalid indices and throws and exception if you make a mistake - that's not a bad idea while you're learning the language. – Tony Delroy Apr 29 '17 at 01:08
  • You need to change your second for loop condition to be `j<5;`, remember that arrays are 0 based. 0,1,2,3,4 = 5 elements. – nitronoid Apr 29 '17 at 01:10
  • @bipll...What does changing 'd' to 'W' does to the logic ? Are you kidding? – 14yearoldprogrammer Apr 29 '17 at 01:12
  • @nitronoid... Thanks I got the answer, as multi-dimension means contiguous arrangement of each dimensional array. So accessing a[0][5] is same as a[1][0]. Thanks. – 14yearoldprogrammer Apr 29 '17 at 01:14
  • @TonyD Thanks for vector::at() ....thats helpful. – 14yearoldprogrammer Apr 29 '17 at 01:17

1 Answers1

1

You might be treating this issue like an out-of-bounds error in Java, where the behavior is strictly defined: you'll get an ArrayIndexOutOfBoundsException, and the program will immediately terminate, unless the exception is caught and handled.

In C++, this kind of out-of-bounds error is undefined behavior, which means the compiler is allowed to do whatever silly thing it thinks will achieve the best performance. Generally speaking, this results in the compiler just blindly performing the same pointer arithmetic it would perform on array accesses that are in-bounds, regardless of whether the memory is valid or not.

In your case, because you've allocated 25 chars worth of memory, you'll access valid memory (in most environments, UB withstanding) at least until i * 5 + j >= 25, at which point any number of things could happen:

  • You could get garbage data off the stack
  • You could crash the program with a Segmentation Fault (Access Violation in Windows/Visual Studio)
  • The loop could refuse to terminate at the index you expect it to terminate.

That last one is an incredible bug: If aggressive loop optimization is occurring, you could get some very odd behavior when you make mistakes like this in your code.

What's almost certainly happening in the code you wrote is that that first point: though you allocated space for 25 chars, you only defined the contents of 10 of them, meaning any accesses beyond those first 10 will invoke a different kind of undefined behavior (access of an uninitialized variable), which the vast majority of the time, results in their values being filled in with whatever coincidentally was in that memory space before the variable was used.

Community
  • 1
  • 1
Xirema
  • 19,889
  • 4
  • 32
  • 68
  • 1
    Any elements of a brace-initialized array that don't have explicit initializers are defined to be value-initialized. That means that all of them are initialized to `char{}`, which is `'\0'`. Reading them will not result in undefined behavior. That's why `char[10] foo = {}` works to zero-fill an array of `char`s. The behavior of OP's code is undefined though, since `a[0][5]` accesses outside the array `a[0]`. You'd be hard pressed to find a compiler where it doesn't just end up accessing `a[1][0]` though. – Miles Budnek Apr 29 '17 at 01:26
  • Thanks for introducing me to this "undefined behavior". It helps a lot. – 14yearoldprogrammer Apr 29 '17 at 01:28
  • 1
    @TonyD I fixed it. – Xirema Apr 29 '17 at 19:36