Like variables, arrays in C++ are static. Their size must be known at compile time, and the compiler allocates appropriate amounts of memory.
Even though arrays look like pointers, that is, they have a value which is a memory address, you can't even assign them. Program 1 has two arrays and tries to assign the first array to the second.
Program 1. Assigning arrays.
#include <iostream> using namespace std; int main() { const int N = 5; int a[N] = {0, 1, 2, 3, 4}; int b[N] = {1, 2, 4, 8, 16}; b = a; return 0; } |
If you try to compile this, you get the error:
In function `int main()': 19: error: ISO C++ forbids assignment of arrays
Therefore we cannot use arrays to dynamically allocate memory for variable sized objects, such as a Microsoft® Word document, or even a text file. Thus, if we want to have arrays which have different sizes, we need arrays (or something like arrays) which can by set dynamically.
Consider Program 2.
Program 2. Going beyond the extremes of an array.
#include <iostream> using namespace std; int main() { const int N = 5; int c = 12345; int a[N] = {10, 11, 12, 13, 14}; int d = 67890; for ( int i = -2; i < 7; ++i ) { cout << "a[" << i << "] = " << a[i] << endl; } return 0; } |
If you run this code, you get:
a[-2] = -2 a[-1] = 67890 a[0] = 10 a[1] = 11 a[2] = 12 a[3] = 13 a[4] = 14 a[5] = 0 a[6] = 12345
The first thing you may ask is: didn't I say that the array int a[5] has entries a[0] through a[4]? Yes, that is how much memory is allocated, however, nothing in C or C++ prevents you from accessing memory locations outside of that range.
If you examine the output, you will note that there are some interesting similarities, as is shown in Figure 1.
Figure 1. The value of array entries outside of the given bounds.
The very first thing we notice is that it seems that a[6] is accessing the same memory location which stores the variable c and a[-1] is accessing the same memory location as the variable d. A little more thought makes one realize that a[-2] is accessing the same memory location as i.
To verify this, run Program 3.
Program 3. Accessing the world outside of bounds.
#include <iostream> using namespace std; int main() { const int N = 5; int c = 12345; int a[N] = {10, 11, 12, 13, 14}; int d = 67890; for ( int i = -2; i < 7; ++i ) { // do nothing, I'm just keeping the variable 'i' around } cout << "The variable c = " << c << endl; cout << "The variable d = " << d << endl; cout << "Assigning to a[-1] and a[6]..." << endl; a[-1] = 51423; a[ 6] = 60798; cout << "The variable c = " << c << endl; cout << "The variable d = " << d << endl; return 0; } |
When I view the output, I get:
The variable c = 12345 The variable d = 67890 Assigning to a[-1] and a[6]... The variable c = 60798 The variable d = 51423
This shows that by modifying entries outside of the array that we can modify other variables!!! This is one of the most major source of bugs in C and C++. In Java, it is forbidden to access memory locations outside that specified in the size of the array. Thus, you can never inadvertently change other variables, however, accessing an entry within an array becomes approximately twice as expensive.
Another possibility is that the operating system may terminate the program if you try to access a memory location not allocated by the OS to the running program.
1. Rewrite Program 3 so that it simply prints out the address of c, d, a[-2], and a[6], and confirm that they are pair-wise equal.
2. Write a program which starts to access a[0] and then accesses a[1], then a[2], and so on, until your program crashes. How far does it get?
3. If you wrote your answer to Question 2 using a for loop, rewrite it using a while loop. If you used a while loop, rewrite it using a for loop. Now that you see both, discuss the benefits and drawbacks of each.