tags:

views:

84

answers:

6

Hello,

I'm relatively new to C, and this is baffling me right now. It's part of a much larger program, but I've written this little program to depict the problem I'm having.

#include <stdio.h>

int main()
{
    signed int tcodes[3][1];

    tcodes[0][0] = 0;
    tcodes[0][1] = 1000;
    tcodes[1][0] = 1000;
    tcodes[1][1] = 0;
    tcodes[2][0] = 0;
    tcodes[2][1] = 1000;
    tcodes[3][0] = 1000;
    tcodes[3][1] = 0;

    int x, y, c;

    for(c = 0; c <= 3; c++)
    {
        printf("%d %d %d\r\n", c, tcodes[c][0], tcodes[c][1]);

        x = 20;
        y = 30;
    }

}

I'd expect this program to output:

0 0 1000
1 1000 0
2 0 1000
3 1000 0

But instead, I get:

0 0 1000
1 1000 0
2 0 20
3 20 30

It does this for any number assigned to x and y. For some reason x and y are overriding parts of the array in memory.

Can someone explain what's going on?

Thanks!

+8  A: 

  tcodes[3][0] = 1000;   
  tcodes[3][1] = 0; 

are writing off the end of your array twice. [3] allocates slot ids 0-2 and [1] only allocates 1 actual slot [0].

Change your initialization of tcodes to signed int tcodes[4][2]; for 4 entries by 2 entries.

Michael Dorgan
And `[1]` only allocates slot 0 for each row.
Matthew Flaschen
yep, was typing as fast as I could when i seen that as well :)
Michael Dorgan
+5  A: 

Change it to this:

signed int tcodes[4][2];
Prine
+3  A: 

If You define an array like this:

int somearr[3];

You get an array that has 3 elements. Indexes start form 0, so those elements are:

somearr[0]
somearr[1]
somearr[2]

Arrays and other variables defined inside a function, like in Your code, are allocated on the stack. It just so happens, that variables x and y are placed on the stack next to Your array. If you try to access elements

tcodes[3][0] or tcodes[3][1]

You access a part of a stack, that is behind Your array and, as Your output show, it's the spot, where variables x and y are placed.

In fact definition like this

signed int tcodes[3][1];

creates an array containing 3 elements, each of which is an array too - an array containing one signed int. When You write tcodes[1][1], You are accessing non-existing "second" element of your second array. The place in memory, that the compiler accesses when it interprets tcodes[1][1] overlaps with tcodes[2][0];

Maciej Hehl
+5  A: 

The other answers are right, but to help explain what's actually happening:

You have the following local declarations:

signed int tcodes[3][1];
int x, y, c;

Those get stored right next to each other in the stack frame in memory:

tcodes
x
y
z

tcodes has 3 spots, and trying to write to tcodes[n] just means to find where tcodes points to in memory and move over to the nth spot (I'm going to ignore your second dimension since it was just 1 anyway). If you try to write to spot 3, it's going to move over 3 spots from the beginning of tcodes, even though tcodes isn't that big. Since x is located right after tcodes, in the spot tcodes[3] would be in, that memory gets overwritten and the value of x changes. tcodes[4] would overwrite y, and tcodes[5] would overwrite z. If you kept making n bigger (or negative, which is legal), you could overwrite anything you're allowed to access in memory, which can screw up your program in bad and hard-to-find ways

Michael Mrozek
A: 

As you are writing beyond the array boundaries, you are writing on the memory allocated to x and y variables on stack. In this case, they happen to be same as tcodes[3][0] == x and tcodes[3][1] == y as the addresses are same. If you are doing it in a called function and the array is passed by reference, you might end up in stack corruption. The bottom line is that in C, arrays are 0 based.

multicoredump
A: 

You need to pay attention to the solution given by Robin Oster above. The other folks may be giving you "too much information". Just count the number of items in each dimension better, don't forget the zero'th item counts!

Hotei