Variable value assignment saved in wrong place?

I am relatively unfamiliar with C and this puzzles me right now. This is part of a much larger program, but I wrote this small program to depict the problem I am facing.

#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 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 please explain what's going on?

Thanks!

+2


a source to share


6 answers


The other answers are correct, but to explain what is actually happening:

You have the following local declarations:

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

      



The ones that are stored next to each other in the in-memory stack frame:

tcodes
x
y
z

tcodes

has 3 dots and is trying to write in tcodes[n]

just means find where tcodes

the memory points to and move to n

th (I'll ignore your second dimension since it was only 1). If you try to write to spot 3, it will move three points from the beginning tcodes

, although tcodes

not that big. Since it x

is located immediately after tcodes

, it tcodes[3]

will be in the spot , this memory will be overwritten, and the value x

will change. tcodes[4]

will overwrite y

and tcodes[5]

will overwrite z

. If you keep doingn

more (or negatively, which is legal), you can overwrite whatever you are allowed to access in memory, which can mess up your program in bad and hard-to-find ways.

+5


a source



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

      

flushing the end of your array twice. [3] allocates slot IDs 0-2, and [1] allocates only 1 actual slot [0].



Change the initialization tcodes signed int tcodes[4][2];

for 4 records to 2 records.

+8


a source


Change it like this:

signed int tcodes[4][2];

      

+5


a source


If you define an array like this:

int somearr[3];

      

You end up with an array containing 3 elements. Indexes start at form 0, so these items:

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

      

On the stack are allocated arrays and other variables defined inside a function, for example in your code. It just so happens that the variables x and y are pushed onto the stack next to your array. If you try to access the elements

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

      

You are accessing the portion of the stack behind your array, and as your output shows, this is where the x and y variables are placed.

Actually the type definition

signed int tcodes[3][1];

      

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

+3


a source


When you write the bounds of an array, you are writing to the memory allocated for the x and y variables on the stack. In this case, they are the same as tcodes [3] [0] == x and tcodes [3] [1] == y, since the addresses are the same. If you do this in a called function and the array is passed by reference, you may end up in stack corruption. The bottom line is that in C, arrays are 0-based.

0


a source


You need to pay attention to the solution given by Robin Oster above. Other people may give you "too much information". Just count the number of elements in each dimension better, don't forget to count the zero element!

0


a source







All Articles