Problem with 2-D arrays

How does the following program work?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>

int main()
{
    int a[3][3]={5,5,5,2,2,2,8,8,8};

    for(int i=0;i<=2;i++)
        for(int j=1;j<=2;j++)
        {
            std::cout<<"i="<<i<<"\t"<<"j="<<j<<"\n";
            a[i+1][j]+=a[j][i]; //i should evetually become 3 right?
            a[j][i+1]-=2;
        }

    std::cout<<"\n\n";
    for(int i=0;i<=2;i++)
        for(int j=1;j<=2;j++)
            std::cout<<a[i][j];
    return 0;
}

in the line
a[i+1][j]+=a[j][i];
i would eventually become 3 and then the program should throw an error, but it works perfectly.
I suspect this is due to the fact that 2-D arrays can be treated as 1-D arrays, but how is it that both subscripts are used and the program still works?
Last edited on
(I'm not sure about this, it coud be wrong)
Arrays are constant pointers. That means that there are pointing to a value and if you change the array, you change in fact the value its pointing to.

For so far the theory. The result of this is that you can use an array that dont 'exist'. Its pointing to value and you change that value. As long as you dont change it, you can refer to that value by using the same array index. The following code works fine:
1
2
3
4
5
6
7
8
9
#include<iostream>

int main()
{
    int array[3]={1,2,3};
    array[10]=10;
    std::cout<<array[10];
    return 0;
}

This may works fine, however, in bigger programs it causes problems: here you dont change the value of array[10] before using it, but in bigger programs it problably will. Read the chapter about pointers in the tutorial on this site if you want to know more.
Last edited on
In lines 11 and 12 you have something like this: a[i+1][j].
If i is equal to 2, it would be like writing a[3][j] but that is wrong because you declared a as an array of 3 array of 3 ints each.
In that case you would be referring to the 4th array but is doesn't exist.
Your array is made like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
a:
   a[0]:
        a[0][0] (int)
        a[0][1] (int)
        a[0][2] (int)
   a[1]:
        a[1][0] (int)
        a[1][1] (int)
        a[1][2] (int)
   a[2]:
        a[2][0] (int)
        a[2][1] (int)
        a[2][2] (int)

You can see that a[3] doesn't exists
Last edited on
...

Have you read his question?
i would eventually become 3 and then the program should throw an error, but it works perfectly.
After executing you should get
Run-Time Check Failure #2 - Stack around the variable 'a' was corrupted.
that is because you are referring to an unexisting variable
I know. The problem wasnt an error: the problem was that he did not recieve an error and the program worked fine, while he was using an unexisting variable. The explanation is in my first post.
If you get an error after run-time, i think you have different settings or someting. The code works fine by me (wich is the problem: it souldnt work fine).
I wasnt able to completely understand you scipio, but I made a little modification to your program and tried:
#include<iostream>

1
2
3
4
5
6
7
8
int main()
{
    int array[3]={1,2,3};
    array[10]=10;
    for(int i=0;i<11;i++)
    std::cout<<array[i];
    return 0;
}

And the code worked perfectly. The first three elements were 1, 2 and 3 and the last one was 10. The rest were trash. This would mean that the code
array[10]=10;
is like expanding the length of the array.
Now I'm even more confused.
I will try to explain.
(You need to understand the concept of pointers first: http://www.cplusplus.com/doc/tutorial/pointers.html)

An array is a set of constant pointers. At the moment you declare an array like this: int array[3], the program will reserve place in the memory to store three integer values. You can acces those values by using array[n], where n is 0/1/2. This is in fact a constant pointer to that specific place in memory.

For so far the normal part. Now our problem: wy can you use an array[index] wich we havent declared? Assuming an array is a constant pointer, a declaration as
1
2
int array[3]={1,2,3};
array[10]=10;

will reserve 3 places in the memory and store the values 1,2 and 3 in them, and store the value 10 in the place arrayj[10] is pointing at. This place is not reserved. In the case of a simple program like you got above, this placed isnt used to store another value in before using it. So when you use this:cout<<array[10] the program displays 10 on the screen: you have stored that value a few lines before in this specific place.
However, in a bigger program, you probably will use this non-reserved place in memory, so the program will start acting strange.

I hoop you understand it now.
Last edited on
Ah, I get it now. This would mean that the array would eventually throw an error (if run enough times) because it would try to access memory that was not assigned to the program in the first place (like trying to dereference a pointer to some random memory location).

The funny thing is I know pointers quite well and I've used them quite often. What I had always thought was that an array would immediately throw an error if you crossed its bounds, but now I understand that this is not always true.

The problem doesnt end here though. The thing is that the program I posted initially works as its supposed to, the output matches that given by my teacher and I'm sure she wouldnt have been stupid enough to create a program that could throw an error.

Is there something I'm missing here?
Last edited on
Well, i dont fully understand what your code is trying to do. But it only calculates a[3][j] and a[j][3], not displaying it. So if the output matches with what it should be, is that because the program you have written does the right thing, it only calculates a bit to much :)
What was your assigment?

I dont know what would happen if the array tryes to acces memory that already used. Maybe it would trow an error, maybe it chances the value and causes UB.
Last edited on
Topic archived. No new replies allowed.