0

I run the following code.

#include <stdio.h>

int main(){

int g[2][2]={{1,2},{3,4}};

//trying to print the array(y,x)

int x,y;
x=1;
y=1;
printf("element (%d,%d) of array is %d", y,x,g[y][x]);

return 0;
}

Most of it runs fine. I get the results g[0][0]=1, g[0][1]=2, g[1][0]=3, g[1][1]=4. But when I try to access elements like g[2][0], i get 2. similarly g[2][1]=1, g[0][2]=3, g[1][2]=1. I would have expected if any of the index was 2, i would get a grabage value. This does happen for (2,2) and for indices 3 and above. But I dont understand how elemnts like g[2][0] are accessed.

Can someone help me understand this? I want to understand this because I want to write a code for periodic boundary conditions where I will need to access the elements outside the array.(I am relatively new to learning C and dont thoroughly understand the pointers and 2d arrays thing.)

  • 3
    What makes you think that the specified values are not garbage values? Accessing an array out of bounds causes [undefined behavior](https://en.cppreference.com/w/c/language/behavior). – Andreas Wenzel May 03 '21 at 14:44
  • Also, I don't see a comma between `{1,2}` and `{3,4}` – Silidrone May 03 '21 at 14:46
  • Does this answer your question? [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – Andreas Wenzel May 03 '21 at 14:49
  • What you call "garbage" is *indeterminate* (see e.g. https://stackoverflow.com/questions/11962457/why-is-using-an-uninitialized-variable-undefined-behavior) and it isn't necessary an "ugly" value, it could be a seemingly innocent value, like 0. – Bob__ May 03 '21 at 14:50
  • 2
    _I want to write a code ... where I will need to access the elements outside the array._ Then you need to re-architect your code. If you find yourself _needing_ to invoke undefined behavior something about your code design is very wrong. – yano May 03 '21 at 14:52
  • When you provide code samples, you should try to make sure, the code is correct. Here x and y are not declared and there is a missing comma in the array initializer. – lulle2007200 May 03 '21 at 15:09
  • @AndreasWeznel I tried looking at the value of g[2][0] after changing g[1][0] to 30. now g[2][0] prints 30. So im guessing the array is accessing elemensts inside itself. – YeetTheorem May 03 '21 at 17:39
  • @lulle, Oh...I didnt see that. Is it really important though? I thought the code was simple enough that improper syntax wouldnt make that much of a difference. I'll keep this in mind for the next time. Thanks – YeetTheorem May 03 '21 at 17:43
  • @YeetTheorem a) It's just good form. Those mistakes are easy to fix since you get compiler warnings. b) When people want to test/modify/do whatever with you code sample, they can just copy/paste it and don't have to fix a bunch of trivial mistakes first. – lulle2007200 May 03 '21 at 17:53

2 Answers2

3

In C, nothing prevents you from trying to access out of bounds memory. It is undefined behaviour, it may cause an access violation, you may get unexpected garbage data or - the worst case - you get exactly the value you expected.

Also you say

where I will need to access the elements outside the array

You are not allowed to do that, but nothing will prevent you from doing so. Doing so by accident leads to all sorts of bugs (see off-by-one), doing it intentionally is a very bad idea.

g[0][2]=3

Think about what element of the 2D-array you are accessing here. You are accessing the third element of the first line of of your 2D-array, which maps to the first element of the second line. This won't even cause an access violation, but may still cause bugs.

lulle2007200
  • 888
  • 9
  • 20
  • This seems like this could be the issue. Could you help me understand a bit about how does one go from g[y][x] to which element of the array is being accessed? I thought if the index was >=2, it would automatically lead to accessing an elemnt outisde array. – YeetTheorem May 03 '21 at 17:45
  • Detail :"nothing prevents you from trying to access out of bounds memory. It is undefined behaviour," contradicts itself a bit. A C implementation very well might prevent such access, it might not. It is UB. With UB, the behavior is not defined and neither defined is what might not happen. – chux - Reinstate Monica May 03 '21 at 18:01
  • Could have worded it better i guess. You can *try* to access out of bounds memory, but the outcome is undefined. Re " Could you help me understand a bit...": See YeetTheorem's answer – lulle2007200 May 03 '21 at 18:13
1

grabage value

That's it :)

A value you've just grabbed from somewhere.

As long as you stay inside the allocated region, this is OK. You have 4 ints starting at g. No pointers.

But g[2][0] is beyond the array address. Grabbage!


My pointer formula was very wrong. Here a tested version with different alternatives to g[0][3] I think this is OK, and you can also choose a middle slice as base, as long as you calculate the max. offset correctly.

#include <stdio.h>

int main(){

int g[2][2]={{1,2},{3,4}};

int x=3;  // column index too high
int y=0;  // but low row

printf("element (%d,%d) of array is %d\n", y,x,g[y][x]);   // original


printf("same %d\n", *(*(g + y) + x));  // one y is 2 ints, needs nesting

int *g0 = g[0];                        // shortcut to g[0]
printf("same %d\n", *(g0 + x));
printf("same %d\n", g0[x]);            // 1-Dim array

int *g0plus = g0 + x;
printf("same  %d\n", *g0plus);         // 0-Dim array

printf("elements %ld\n", sizeof g/sizeof(int));

printf("one beyond %d\n", g0[x+1]);
return 0;
}

This all ("same") prints out the last value "4", also for "elemente".

"One beyond" is -1677831440. That is what I call garbage.

  • Oh...I get it now. This combined with the other answer makes things clear. Thanks! (also lol) – YeetTheorem May 03 '21 at 17:50
  • I just corrected / added. Didn't catch the g[0][2] vs g[2][0] case at first. Big difference. And if you really want g[0][2], I put some examples. Makes more sense for 10x10x10 arrays or so. –  May 03 '21 at 18:26