Time now for arrays. Arrays in C++ are essentially pointers that point to the first of a series of sequentially stored pieces of data. This basically means that you can invoke any of that data with one variable name. Unfortunately, they're very limited. In their simplest forms, they do not allow you to modify the size of the array, neither is the size of the array implicitly passed along with it -- you must pass the size along as a separate variable. That said, they are still an important stepping stone into more complicated techniques, and they are always useful in their own right no matter how limited they are.
Before we dive into arrays, however, I must show you the "real" way to allocate memory. If you remember the last lesson, you did this simply by declaring a variable. This obviously won't work for variables, but there are a few other options available to you. The first is a function called malloc, which takes one parameter: the number of bytes you want the program to allocate. However, there is a caveat: malloc returns memory of the data type void*, so you have to convert it over to your desired data type. To do that, simply put your data type and an asterik in parentheses in front of the malloc function. In addition to all that, you need the sizeof function, which takes a parameter of any data type and converts it into the number of bytes of memory that data type requires. Is it all falling into place yet? If not, have a look at this example:
int * a = (int*)malloc(sizeof(int));
That operation is essentially the same as our pointer delcaration in the last lesson, except we have eliminated that extraneous integer declaration. From here, creating an array is simple: You simply do this:
int * a = (int*)malloc(sizeof(int) * 5);
That's right! Arrays are simply pointers with more than one "unit" of memory allocated to them. This example will have 5 "elements." That is, it will hold 5 integers. Using them is a little more strange, though. Take a look at this box which represents the array we just created.
| 1 | 2 | 3 | 4 | 5 |
The numbers represent the elements of the array, 1-5. However, there's also an index which is basically a mathematical way for it to take the location in memory stored by the array -- in this case "a" -- and jump over to the other elements. Printing a by itself right now will simply give you the first element; adding one to it will give you th second element; adding two will give you the 3rd element; and so on in that fashion. This is indexing, and it is what the computer uses to invoke the elements of an array: just remember element - 1 is the index you're looking for. So how do you use this? In the exact fashion I just described: add one or two (or whatever) to your array variable! Here is how it works (assuming that the declaration above has already executed) -- remember the asterik!
*a = 20; *(a + 1) = 25; *(a + 2) = 30; *(a + 3) = 35; *(a + 4) = 40;
The first one could easily have been rewritten to *(a + 0), but that is a little reduntant now isn't it? If you'd like to know the inner workings of how indexing works, it is a simple process. You remember that arrays are stored sequentially with each element taking up sizeof(data type) bytes of memory, right? Well, since a is pointing to the first byte of the first element of the array, multiplying the index by sizeof(data type) and adding it to the array variable will (temporarily) move the pointer right to the first byte of whatever element you chose. The asterik tells it to provide the value stored rather than the location in memory, and you're set! You may have noticed the conspicuous lack of sizeof's and multiplication operations in the previous examples. That is because the compiler does all of those operations itself when you add to or subtract from a pointer. This is called pointer math. Remember, though, that if you go outside the bounds of the array it will not return an error; it'll just give you gibberish when you use it.
Now that you've learned the "basic" way to use arrays, there is a "higher level" way of doing it using brackets ([]). To declare an array in this manner, simply remove the asterik and place the brackets after it. From here, you have a few new options. You can leave the brackets empty and initialize every element right then and there, or you can put a number in the brackets which will allocate that many elements into the array. To do the former, you simply set it equal to curly brackets ({}) containing the comma delimited values. The number of values will determine the of the array. The latter method is self explanatory.
Finally, you can invoke the values of the elements in the same fashion. Just omit the asterik, append the brackets and place the index within them.
int a[5];
int b[] = {1,2,3};
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
cout << b[0] << ", " << b[1] << ", " << b[2] << endl;
As you can see, this method is a bit easier to work with. While this method is easier to work with in principle, it makes it easy to lose sight of how it all works, which might prove troublesome as you move to more advanced techniques. However, your mileage may vary. So long as you can remember the underlying operations and the logic behind it, there is nothing wrong with using this method.