Understanding Arrays

I am currently studying arrays. I think that I understand how they work, i.e., how they are filled, how elements are accessed, etc.) However, I have run into an example in my text that doesn't make sense to me. I thought it might be a misprint, so I actually ran the code and got the same result as the book. Here is my problem:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main()
{
    int data[4];
    
    for (int i = 1; i <= 4; i++)      // Fill all 4 places of array
        data[i] = i;                 
    for (int i = 1; i <= 6; i++)      // Print 6 places -- error
        cout << data[i] << endl;  
    return 0;
}


This code is supposed to demonstrate what happens when out-of-bounds array indices are accessed.

Here is the output when I run the code snippet:
1
2
3
4
2130567168 (out-of-bounds)
2686840 (out-of-bounds)

I was expecting the output to give 3 values and 3 out-of-bounds numbers such as:

1
2
3
23145 (out-of-bounds)
32145 (out-of-bounds)
5342 (out-of-bounds)

The way the first for loop is written, I would expect 1 to be input into data[1] which would be the second array position,
given that data[0] is the first position. Then, I would expect 2 to be input into data[2] and 3 to be input into data[3] (the last valid array position. Then, when the second for loop runs it would output values found in data[1], data[2] and data[3] and
that the next three output values would be whatever is sitting in the memory cells beyond the end of the array. Can someone
help me understand where I am missing this? Thank you in advance.
That's the problem with arrays, they don't work the way you expect!

When you are doing the first loop the array doesn't care if you're going out of bounds or not. It will write to the location of memory of array element 4, where it calculates the forth member to be. That means, even if you only reserve 4 spaces (0 to 3) you can write to 4 and -1. This is what makes arrays so dangerous and is the main reason behind a lot of exploits in code. You could write in an array define to be 4 units long up to 1000! And printing it out you'll see all the numbers put in.

Not of course this is bad as you are overwriting memory that isn't reserved, and that means you can be overwriting important values to other programs, other functions in your code and other harmful things.
Thank you wolfgang, that makes sense. So for i=4, it isn't actually going into data[4], because that index doesn't exist in my 4 element array, but rather it is putting 4 into a memory address beyond the end of my array. I'm still not quite clear on how it retrieves that value when they are output as a function of the array. I guess, it just reads the address beyond the end of the array where I stored i=4 and outputs it anyway.
It can retrieve it because it writes the value of 4 in binary into that location of bytes. So that memory holds:
00000000 00000000 00000000 00000100 which casted to an int returns the number 4.

Ever wonder how you get random numbers for non-initialized ints? Its the value that was there before, but that value didn't have to be an int, it could have been an old pointer and the data it held an address location. If you don't initialize ove that data you are using the byte sequence originally there to mean an integer value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

int main()
{
  int i = 2903;
  int *data = &i;

  cout << *data << endl;
  cout << data << endl;
  cout << (int) data << endl;

  return 0;
}


You can run this code to see what I mean. The first cout shows what data points to (in this case 2039). The second what what is actually in data. The last is what happens if I took the binary that represents the pointer and called it an integer.
Weird number eh?

The real point is arrays are more so pointers. They hold a series of values but an array actually only knows what the first element is in the array. The [] operator does "pointer arithmetic" which adds to the address of the first element and then gets the value at the address. Arrays, as pointers don't check their bounds so they are free to go far into the memory as long as it can do the math (or as long as the computer and compiler allow it. Some compilers will stop you and some computers will crash or throw up errors.)

A little more on arrays to show that its a pointer:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;

int main()
{
  int val[5]; // Array of 5

  for (int i = 0; i < 5; ++i)
    val[i] = i * 2; // Some values

  int *pointer = val; // Note I need no & infront here.

  cout << val << endl; // Pointer address? What is this?
  cout << pointer << endl;

  cout << *val << endl; // The same value?
  cout << val[0] << endl;

  cout << *(val + 2) << endl; // Pointer arithmetic!
  cout << val[2] << endl;

  return 0;
}
Last edited on
closed account (1yR4jE8b)
you can be overwriting important values to other programs


Unless you are using a 20 year old operating system like MS-DOS, your program will crash from a segmentation fault/access violation before this happens. Modern operating systems don't let programs write into the memory of other programs.
Topic archived. No new replies allowed.