Commentary: Basic Arrays

Chris Wild & Steven Zeil

Last modified: Jul 7, 2017
Contents:

Arrays are convenient for naming and using a collection of objects of the same type.

1 Static Sized Arrays

The most common way of setting up arrays in beginning C++ programs is static allocations:

int myArray[100];
string myOtherArray[100];

This declares one array of integers and another of strings, each containing 100 elements.

The array size must be a constant. It can be a named constant, but it must be a value that is computed and fixed when the code is compiled:

const int MaxSize = 50;
int fakeSize = 50;
  ⋮
int myArray[MaxSize]; // OK
int myOtherArray[fakeSize]; // compilation error!

fakeSize does not work here because it’s not a constant. We can look at it and guess the it has the value 50, but it’s possible that somewhere in the region there are some calculations that change the value of fakeSize, so the compiler can’t tell fur sure that fakeSize will still be 50 when execution reaches the declaration of the array.

2 Operations on Arrays

The major thing that we do with arrays is to use [ ] to retrie or alter individual elements of the array.

myArray[i] = myArray[0];

That’s pretty much it.

Arrays do not know their own limits. In many programming langauges would could say something like myArray.length or myArray.sizeto ask the array how many elements it really has. Not in C++. C++ arrays just aren’t that self-aware. If you need to know the size of an array, you need to keep track of it yourself.

Arrays do not copy easily. This code won’t actually compile:

int array1[100];
for (int i = 0; i < 100; ++i)
    array1[i] = i;
int array2[100];
array2 = array1;  // No!

It will get a compilation error on the final assignment. But there is some fairly similar array code that would compile. Nonetheless, when it executes, it does not make a copy of the array.

As in Java, Python, and quite a few other programming languages, a C++ array is actually a reference/pointer/address. If you tweak the array declarations in the above code enough to get it to compile, it would still not make a copy of array1. Instead it would copy the address of array1 into the variable array2, giving you two variables, array1 and array2, that actually access the same underlying array.

3 Arrays and Functions

3.1 Parameters

Similarly, because array variables really hold references/pointers/addresses, when you pass them to a function, even if you pass-by-copy, the function receives a copy of the address, not a copy of the array value. The net effect is that arrays are always passed by reference.

3.2 Return Values

And, you can’t really return an array from a function via a return statement. You can return an address of an array, but that cab be a tricky thing to do. For example, this would compile

const char* myName()
{
    const char* result = "Steven Zeil";
    return result;
}

Usually when we return from the body of the function, any variables declared in the function body are destroyed. So here, when we return result, we are actually returning the address of the character array "Steven Zeil". But that array is introduced inside the body of the function myName(), which means that, when we return from the call, it may be destroyed. We will then have passed back to our caller the address of an array that no longer exists.

3.3 Two Ways to Name an Array Type

There are actually two different type expressions that get used to describe array types that you might pass into a function. These two functions actually mean and do exactly the same thing:

int foo (int[] a)
{
 return a[0];
}

int bar (int* a)
{
 return a[0];
}

The function foo indicates an array type using []. But, because arrays are really addresses, bar can do exactly the same thing by indicating an array with *, which actually means “pointer to” “address for” the type just preceding.

Both are quite common in C++ code.