0

I'm currently learning C++ as of yesterday and I have come across this new thing called an array. All I know about them so far is that they can hold data in a sort of table aspect and you can modify/read the data that they hold.

Since I'm experimenting with C++ I thought I would try to break it and it made me ask this question right now. When I try to read from a value that isn't specified, I get a number and I'm not sure why it is being caused.

int lotteryNumbers[5] = {10, 20, 30, 40, 50};
// Yes, I know that the loop count is 5!
    for (int loopCount = 0; loopCount <= 5; loopCount++) {
        cout << lotteryNumbers[loopCount] << endl;
    }

My output is;

10
20
30
40
50
13439729 <-- What is this sourcery?!

Any help would be much appreciated to guide me learning this complicated language.

Thanks, Nathan.

EDIT: THANK YOU FOR YOUR HELP. NOW MARKED AS DUPLICATE. :D

Nathan
  • 41
  • 4
  • You have 5 numbers, you're reading six. 0, 1, 2, 3, 4, 5. Not sorcery, just common sense. Get a good book on C++ if you're beginning; learning by asking questions on SO is not very efficient. – Jonathan Potter Aug 18 '16 at 09:55
  • @JonathanPotter **I know I'm reading the sixth value**. I want to know what causes the number, why is it '13439729'? – Nathan Aug 18 '16 at 09:57
  • 2
    Its just what happens to be in that memory position interpreted as an int – Robin Gertenbach Aug 18 '16 at 09:59
  • Why do this answer gain downvotes? It is such a good answer, except that it is duplicate :) – ikh Aug 18 '16 at 10:04
  • Oh shoot, didn't realise that it's a duplicate. I'm new to this website and so I'm not sure how to find things easily. :p – Nathan Aug 18 '16 at 10:08

3 Answers3

6

C++ gives you the ability to shoot yourself in the foot: arrays are not bounds-checked at runtime.

It's down to you to make sure you only refer to indexes within the array.

The behaviour on reading an index outside the array is undefined. Anything could happen: including the printing of what's at that location in memory (which could well be happening in your case - check with your debugger). Or the compiler could eat your cat.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 2
    @Nathan While adjacent memory might be the underlying explanation, focusing on that too much might lead you to a world of inconsistent pseudo low-level thinking that's prevalent among C and C++ beginner programmers. It's best to focus on the part of the answer that says that the behavior is *undefined* and that *anything* could happen. It will give you a much better mental model of C and C++ UB in the long run. – Theodoros Chatzigiannakis Aug 18 '16 at 10:02
  • You forgot the obligatory recommendation of `std::vector` and `std::array` :) – StoryTeller - Unslander Monica Aug 18 '16 at 10:06
  • @TheodorosChatzigiannakis I just looked up memory on cplusplus.com and I literally just closed down my browser as it looks so complicated. If I get a value that I don't understand I'll just think that it's **undefined** as you said. :) – Nathan Aug 18 '16 at 10:06
  • @Nathan: I've found you only need to examine the memory during a 3am debugging session on a production server when the markets open in 5 hours. It's best to learn how to use such tools in advance. Debugging skills are more important IMHO than programming skills. – Bathsheba Aug 18 '16 at 10:08
  • @Nathan Undefined is whatever the spec says is undefined. Sometimes a bizarre value is very well-defined (i.e. it's portable and will be respected by future compilers and all optimization passes) but still an indication of a bug in your business logic. – Theodoros Chatzigiannakis Aug 18 '16 at 10:27
4

Arrays are not bounds-checked at runtime. You have total of 5 entries and by starting it from 0, it ends up at 4. lotteryNumbers[5] will return you a garbage value, as last index is 4.

It should be:

int lotteryNumbers[5] = {10, 20, 30, 40, 50};
// Yes, I know that the loop count is 5!
    for (int loopCount = 0; loopCount <= 4; loopCount++) {
        cout << lotteryNumbers[loopCount] << endl;
    }

Best practice is to use the Size of the array.

Aamish Baloch
  • 1,200
  • 12
  • 9
3

Unlike another "modern" language like Java, C# or Python, C++ has philosophy of "not pay for what you don't use". Array bound check requires some runtime overhead, and it doesn't need for other "legal" programs that doesn't have array bound error.

When the code lotteryNumbers[5] is executed, the program falls in Undefined Behavior. C++ Standard doesn't specify what happens if the undefined behavior is occurred. In these case, the program would read some uninitialized stack-memory, so you can see a "trash" value like 13439729.

If you want bound check, you can use std::array<>::at function.

#include <array>

std::array<int, 5> lotteryNumbers = { 10, 20, 30, 40, 50 };
std::cout << lotteryNumbers.at(5); // throw std::out_of_range

Notice that I use std::array, not plain array. It is a modern-style array which is added in C++11.

ikh
  • 10,119
  • 1
  • 31
  • 70