0

I wrote this code and ran it:

#include <stdio.h>

int i;
int a[] = { 1 };

int main()
{
    for (i = 0; i < 10; i++)
        printf("%d\n", a[i]);
};

It always gave me the following result

1
0
2
0
0
0
0
0
0
0

I know the length of a[] is 1 and a[1],a[2]... are invalid. But I re-compiled it again and finally I found a[2] always give 2, I am quite confused about the 2, where did it come from and why a[2] is not other numbers such as 0 or some random number?

WW00WW
  • 417
  • 4
  • 15
  • You're invoking undefined behavior by going out of bounds of the array. Which is valid, but a big no-no. The numbers you're getting are just 'random' numbers happening to be in that area of you programs memory. It could also crash your program, hence undefined behavior. – Neijwiert Mar 13 '19 at 10:32
  • It comes from reading memory which is not yours. It's undefined behaviour. – Jabberwocky Mar 13 '19 at 10:33
  • `a[]` -> `a[N]`. – Lundin Mar 13 '19 at 10:33
  • BTW what output did you expect when running this program? – Jabberwocky Mar 13 '19 at 10:34
  • @Lundin true, mine was focused on C++, I have deleted my suggestion. – Jose Mar 13 '19 at 10:35
  • 1
    @Neijwiert, in what sense is it "valid" to access an array via an out-of-bounds index? Exercising undefined behavior is practically the essence of *in*valid. – John Bollinger Mar 13 '19 at 10:38
  • @JohnBollinger I worded it incorrectly. Valid in a sense that the compiler is fine with it and valid in a sense that it may or may not execute (which in that case should be invalid). – Neijwiert Mar 13 '19 at 10:42
  • @Neijwiert @Jabberwocky Sorry for the late response. I understand that that is the wrong behavior. But what exactly I wonder is that why `2` is in the result always? I've re-compiled it again and again, but it always `2` in that position, why not `0`? – WW00WW Mar 13 '19 at 11:10
  • @Lundin Sorry for my late response, I just update the question. I think this question might be not a duplication – WW00WW Mar 13 '19 at 11:20
  • @Voldikss If you have a new question, then please ask a new question instead of editing and changing the meaning. There are posted answers and when you edit, you invalidate them, which is not ok. I did a rollback of your changes (see edit history). But the new question is not a good one anyway, see my comment below Sean's answer. – Lundin Mar 13 '19 at 11:24
  • 1
    @Voldikss It just happens to be that way every time you compile it with the compiler you're using. [this](https://onlinegdb.com/SJVb1_ID4) example also happens to have the same output if you leave out the `int b` variable. But notice how `b` happens to be printed out now. The compiler decided that `b` is located directly after `a` in memory. You should never rely on this, the compiler may change it. – Neijwiert Mar 13 '19 at 11:55
  • @Neijwiert Thank you so much for your explanation! I get it~ – WW00WW Mar 13 '19 at 12:05
  • @Neijwiert, I accept that the expression `a[i]` conforms to C syntax, but the action of "going out of bounds of the array" is *never* valid. Moreover, although a compiler may nevertheless accept the code, it is not obligated to do so, the correctness of its syntax notwithstanding. That a compiler may or does accept the code is quite a different thing from the code or the behavior it represents being valid. I acknowledge that this may be nitpicky, but it is important to be precise when talking with someone, such as the OP, who may not be equipped to see through imprecision. – John Bollinger Mar 13 '19 at 13:21

1 Answers1

4

When you do

int a[] = { 1 };

the number of elements in the array will automatically be adjusted to be equal to the number of elements in the initializer. In this case the initializer contains 1 integer so your code is equivalent to:

int a[1] = { 1 };

You've got an array of length 1 but in the for-loop you are accessing 10 items in it (i.e. accessing a[0], a[1], ... a[9]). This is undefined behavior, and what you are seeing is the data beyond the end of your array.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
Sean
  • 60,939
  • 11
  • 97
  • 136
  • Thank you for your explanation and please excuse me for my late response. I understand that that is the wrong behavior. What exactly I wonder is that why `2` is in the result always? I've re-compiled it again and again, but it always `2` in that position, why not `0`? – WW00WW Mar 13 '19 at 11:12
  • I know that `a[2]` is undefined, it refers somewhere in the memory in my computer. But why it always give me `2` while not other numbers such as `0`? – WW00WW Mar 13 '19 at 11:15
  • 3
    @Voldikss There doesn't have to be a rational explanation for it. And it is usually not meaningful to ponder the result of undefined behavior, as there's usually nothing of interest to learn about. Basically you are asking "when I dropped this glass to the floor so that it shattered, why did some of the pieces end up under the dinner table". I'm sure there's an explanation but why would you care - simply avoid dropping glasses. – Lundin Mar 13 '19 at 11:22
  • @Lundin Thanks man, I understand it~ – WW00WW Mar 13 '19 at 11:25
  • One thing to note as well, if you ever use strlen or sizeof to determine the length of an array with underfined length i.e. array [ ] it will always go out of bounds before terminating. Always declare array lengths where possible i.e. array[5], array[32] etc – BitShift Mar 13 '19 at 12:42
  • @Medicineman25, that is ***false***. Evaluating a `sizeof` expression *never* performs an out of bounds access, and whether `strlen()` of an array with implicit size attempts out of bounds access depends on its initializer. If the initializer is a string literal, then `strlen` on it is fine. Otherwise, it might or might not be ok. – John Bollinger Mar 13 '19 at 13:09
  • @John Bollinger my apologies, you are of course correct. I've just double checked and I made the obvious mistake of using sizeof on int types without dividing the result by 4, thus causing my iterator to be of a much greater size. – BitShift Mar 13 '19 at 14:01