Introduction to Arrays
Learn about arrays, why we need them, and how to use them.
We'll cover the following
What are arrays?
An array is a collection of the same type of elements that are stored in a
Think of an array as a bookshelf that has several books placed on it. We can say that we have an array of books. Now, suppose we wish to read the book, The Art of Computer Programming (placed on the 5th location on the shelf). We’ll have to access the book (element) from the shelf (array).
We can do this in two ways:
-
We either fetch the fifth book (element) directly.
-
In case we don’t know which place (index) the book is, we’ll have to traverse the shelf (array) from the first index to the index on which the book is placed.
In C/C++, the indexing of arrays starts from
0
and not1
. In some languages, the array indexing starts from1
.
Why do we need arrays?
With arrays, we can store a number of similar data elements together and can easily access elements, compare them with each other, or even arrange them as needed.
Remember what we did to find the maximum number out of different numbers? We stored each number in a different variable and then compared the first value (assumed to be the maximum) with all values and updated the max
accordingly.
We can use this method if the total numbers are 5, 10, or even 15. But what if there are a total of 50, 100, or 1 million numbers, and we need to find the maximum number? We can’t possibly think of making 50 or 100, or 1 million variables to store all those numbers. That would be too tiring and boring!
In such cases, our go-to solution is the arrays! With arrays, we can store a large number of the same type of data. Not only that, we can traverse through them efficiently.
Let’s discuss this powerful idea of arrays in C++.
Syntax of declaring an array
In C++, the syntax used to declare an array is as follows:
datatype array_name[const_int_size];
For example,
float marks[10];
Here, we declared an array named marks
of type float
and size 10
. This array can hold 10 floating-point values.
There are two types of arrays:
Types of array
- Single-dimensional array
- Multi-dimensional array
Visualizing the arrays
Look at the following code snippet:
int num1=2;...int num2 = 8, num3 = 9;...int num4 = 1;.....int A[4] = {2,8,9,1};
If we look at the illustration below, we have four variables, namely num1
, num2
, num3
, and num4
, residing in a memory block, and they may not be contiguous.
With arrays, all four values, int A[4]={2,8,9,1}
, are stored in a contiguous memory location. For simplicity’s sake, we’ve shortened the hexadecimal addresses appearing in the illustration. However, if we observe, the address of each value is incremented by 4 because each integer value takes 4 bytes.
For a bool
type array, each element of the array would take 1 byte (not 4) of memory because the bool
type uses 1 byte to store a true
or false
value. The increment in address is dependent on the data type of the array.
The indexing of an array starts from
0
and goes up tosize-1
.
How to use arrays
There are many ways to access the elements of an array. We’ll learn about them as we go through the lesson.
In the illustration above, we declared an array A
where the first element is A[0]
, which stores 2
. The second element is A[1]
, which holds 8
, and so on.
The last value is at index size-1
(4 - 1 = 3), so A[3]
is the last value.
We can think about the array name as the base address of the first memory location and these indices as the offset, i.e., how much we have to move forward from the base address.
Now that we’re done with the basics, let’s see how we can declare and initialize an array.
Declaring and initializing arrays
In the program below, we declare and initialize an array and then print the values stored inside of the array.
Array declaration
Let’s say we create an array of integers called A
of size 5
(meaning we can store 5 integer type values):
int A[5];
If we want to print the array elements, we would only get the garbage values. This is because we haven’t initialized the array yet.
Run the code below to see what happens when we print the array’s values without initializing them first. Step by step, execute the program and see in the memory:
#include <iostream> using namespace std; int main() { int A[5]; // All values will be garbage // printing the values stored inside the array cout << A[0]<<" "<<'\n'; // garbage value at zeroth index cout << A[1]<<" "<<'\n'; // garbage value at first index cout << A[2]<<" "<<'\n'; // garbage value at second index cout << A[3]<<" "<<'\n'; // garbage value at third index cout << A[4]<<" "<<'\n'; // garbage value at fourth/last index return 0; }
Array initialization
To initialize the array above, we can write the values we want to assign inside the curly braces like this:
int A[4] = {2, 8, 9, 1};
We’ve initialized with values 2
, 8
, 9
, and 1
, respectively so that A[0]
will access the memory of 2
, A[1]
will access the memory of 8
, and so on.
Look at the animation below to see how by using A[i]
(where i
is equal to the index of the array element), we can access each element of the array.
Understand the following code and its animation:
int A[4] = {2, 8, 9, 1};for(int i=0; i<4; i++){int element = A[i];}
In case we add the curly braces without writing any values inside them, then all values are initialized to zero.
int A[5] = {};
Run the code below to see for yourself:
#include <iostream> using namespace std; int main() { int A[5]={}; // All the values initialized to 0 for(int i=0; i<5; i++) cout <<"Address of index "<<i<<" is "<<A+i<<": and value is "<< A[i]<<"\n"; return 0; }
Note that whenever we write cout<<arrayName
, it prints the base address (from where the array is starting) of the array. Similarly, arrayName+i
will print the i
th location (address) of the array. Similarly, arrayName[i]
will access the value of the i
th location of the array.
Let us have a small quiz.
Given the code below, what do you think would be printed?
#include <iostream>
using namespace std;
int main()
{
int A[5]={1,2};
for(int i=0; i<4; i++)
cout << A[i]<<"\n";
return 0;
}
Nothing will be printed as there is a logical error.
1
, 2
, and 3
garbage values will be printed.
1
, 2
, and 0
will be printed.
In reference to the quiz above, our array would be initialized like in the image below.
Below is the complete program where we declare and initialize the array and print its elements.
Click “Run” to execute the code below.
Run the code step by step to see how arrays first get declared, initialized (on the side panel under local variables, click “+ A”), and then printed.
#include <iostream> using namespace std; int main() { int A[5] = {10,20,30,40,50}; //A[0] = 10, A[1] = 20, A[2] = 30, A[3] = 40, A[4] = 50 // printing the values stored inside the array cout << A[0]<<'\n'; // value at zeroth index cout << A[1]<<'\n'; // value at first index cout << A[2]<<'\n'; // value at second index cout << A[3]<<'\n'; // value at third index cout << A[4]<<'\n'; // value at fourth/last index return 0; }
Printing addresses and accessing values of the array
We’ve seen how we can access the elements of an array. What if we had to print the addresses of each element of the array?
We can access the address of each element of an array by
We can access the address of each element of an array by using the address operator &
. Or, we can perform simple arithmetic on the base address of the array by adding the offset (index) to the base address of the array.
In the animation below, we print the address using the latter method.
Now click “Run” to execute the code below. Here, we print both the element addresses and the array elements.
#include <iostream> using namespace std; int main() { int A[5]={1,2,3,4,5}; // A[0] = 1, A[1] = 2, A[2] = 3, A[3] = 4, A[4] = 5 // printing the addresses along with the values stored // on each index in the array (address: value) cout << "Printing the addresses using arithmetic: " << "\n"; cout <<A+0<<": "<< A[0]<<'\n'; cout <<A+1<<": "<< A[1]<<'\n'; cout <<A+2<<": "<< A[2]<<'\n'; cout <<A+3<<": "<< A[3]<<'\n'; cout <<A+4<<": "<< A[4]<<'\n'; cout << "Printing the addresses using &: " << "\n"; cout <<&A[0]<<": "<< A[0]<<'\n'; cout <<&A[1]<<": "<< A[1]<<'\n'; cout <<&A[2]<<": "<< A[2]<<'\n'; cout <<&A[3]<<": "<< A[3]<<'\n'; cout <<&A[4]<<": "<< A[4]<<'\n'; cout << " A: \t" << A << '\n'; cout << "&A: \t" << &A << '\n'; cout << "&A[0] \t" << &A[0] << '\n'; return 0; }
In the program above, after initializing the array, we print the address of the zeroth index followed by the value stored on the zeroth index in line 12 and likewise for all the other elements.
We’re adding the index number (offset) in the address to get each address. Since the data type of elements is int
, each hexadecimal address of the next element is obtained by adding four bytes to the previous hexadecimal address.
So, we’re printing the address of the third value in the array by adding two to the base address (A + 2
) of the array.
We’ve printed the addresses using the ampersand operator to access the address of each element (lines 19–23).
The address of the array
&A
is the same as the address of the first element of the array&A[0]
, which is the same asA
.
Printing addresses and elements using a loop
We can print the addresses and values the same way as above using a loop as well as shown in the program below:
#include <iostream> using namespace std; int main() { int A[5] = { 1, 2, 3, 4, 5 }; // Printing addresses and values using loop for (int i = 0; i < 5; i++) cout << A + i << ": " << "A[" << i << "]: " << A[i] << endl; return 0; }
Array elements as references
Look at the following code and see the output:
#include <iostream>using namespace std;int main(){int A[] = { 1, 2, 3, 4, 5}, size = 5;for (int i = 0; i < size; i++){int &ref = A[i]; // every time ref will be pointing to a differentref++; // element of the array.}for (int i = 0; i < size; i++)cout << A[i] << " ";return 0;}
Every time int& ref=A[i]
will be a different memory reference. So, in each iteration, the increment in ref
will increment the element of the array.