Arrays in C++ Explained: Essential Concepts and Usage
What is an Array?
Array is a one-dimensional (can be 2D and 3D also) data structure in C++, that can store similar kind/type of data elements in it. It stores those elements in consecutive memory blocks (even in 2D array).
Advantages
Advantage of using an array is that we don’t have to write different names of variables for all the collection of data elements we are storing in the memory. We can have only one variable name (that is array name) for that collection of data elements and to access each data element we use :-
arrayName[index]
So, the variable name for that collection of data elements(or array) followed by subscript operator [] and inside it index.
Indexing in C++ starts from 0, so , arrayName[0] will give us the first data element of array , in constant time O(1). Even, arrayName[size-1] will give us last element of array in constant time O(1). Thus, accessing any element is easy in array as it takes O(1) time because of indexing.
Disadvantages
We can’t store different types of data elements in an array.
We have to specify a fixed size for static array at time of declaration of array. And so, adding a new data element in array can become not possible if adding it will increase size of array > fixed size. And giving too much of fixed size creates unnecessary memory blocks and garbage values.
Deleting operation in array only skips that data element which we wants to delete and does not actually deletes that memory location/block. So, unnecessary memory is left behind.
Defining an array
An array can be created using two ways:
By declaration
By initialization
Declaring an array
#include <iostream> int main() { // Declare an array of size 10 int arr[10]; // Assign values to the first 5 indexes arr[0] = 10; arr[1] = 20; arr[2] = 30; arr[3] = 40; arr[4] = 50; // Optionally, you can print the array to verify for (int i = 0; i < 10; ++i) { std::cout << "arr[" << i << "] = " << arr[i] << std::endl; } return 0; } //Output arr[0] = 10 arr[1] = 20 arr[2] = 30 arr[3] = 40 arr[4] = 50 arr[5] = -858993460 arr[6] = 32767 arr[7] = 0 arr[8] = 4195760 arr[9] = 1This is how we declare an array a of fixed size 10 and we assign values to each memory blocks created ,after the array is declared. So, we already have some garbage values initially in each memory blocks of the array. If we assign values to only 5 indexes where each index (i) corresponds to i th memory location/block , the rest indexes(or ith locations) will have garbage values(unpredictable values).
Initalize an array
#include <iostream>
int main() {
const int SIZE = 10;
int array[SIZE] = {1, 2, 3, 4, 5}; // Initializing the first 5 indexes
//or
//int array[SIZE] = {[0]=1, [1]=2, [2]=3, [3]=4, [4]=5};
// Displaying the array
for (int i = 0; i < SIZE; ++i) {
std::cout << "array[" << i << "] = " << array[i] << std::endl;
}
return 0;
}
//Output
array[0] = 1
array[1] = 2
array[2] = 3
array[3] = 4
array[4] = 5
array[5] = 0
array[6] = 0
array[7] = 0
array[8] = 0
array[9] = 0
Here, in intialization, the values to the array are assigned at the time of array declaration . If we assign values to only first 5 indices, then the rest of indices (rest of elements) by default initialized to 0 and 0.0 in case of float which will cout as 0).
Address Calculation , representation of array in memory and Base Address of array

When an array is declared then memory blocks each of size of datatype of array are allocated in RAM.
Example:-
int a[10]; //means size or no. of elements of array = 10
This statement / declaration will allocate memory blocks each of size 4 bytes(size of int) in RAM. So, the total size or capacity of array in memory is 4bytes * no. of elements in array = 4bytes * 10 = 40 bytes.
Base Address /Starting Address :- It is the memory address of the first element of an array. In example, 1000 is the base address. 1001,1002,1003 memory addresses are also present in first memory block(as each byte has a memory address), but because 1000 is the starting address of this memory block of 4 bytes , we can represent this complete first memory block with base address 1000.
Other consecutive memory blocks will be represented by their Starting addresses not base address of array.
Any array name is base address of that array.
a= &a[0];
where '&’ is called Address-of Operator.
For Address Calculation of array element A[i] , use below formula:-

How a[i] is same as i[a]
a[i] is an expression where a and i are operands and [] is an operator (subscript operator). Just like how (a+b) is an expression where a and b are operands and + is operator.
The c++ compiler translates a[i] internally as :-
a[i] = *(a+i)
where is de-reference operator, a and i are operands and + is addition operator.
According to commutaive law, we can write
(a+b) = (b+a)
So, using same law , the expression *(a+i) can also be written as :-
\(a+i) = \(i+a)
Thus,
a[i]= (a+i) = (i+a) = i[a]
a[i] = i[a]
This thing is the answer to “Why array index starts with 0 in C/C++”. Because, in order to get a[0] (first element/data of array), we must have index 0 so that \(a + 0) = \(a) i.e. Value at address a . (Remember writing a or &a[0] is same thing as both denote Base Address. Here '&’ is called Address-of Operator.)

Notice how address calculation is being done here. Since 1000 is a memory address and 3 is index and there is a ‘+’ b/w them, that doesn’t mean that it will do binary addition i.e. 1003. Actually, this is called Pointer Arithmetic. And here we are adding an integer to the pointer a
C++ compiler internally is calculating the address of the index 3 using the formula that we discussed previously OR we can also say that 3 memory blocks are skipped.
The c++ compiler interprets a[i] internally as
a[i] = (base_address_of_a + i * sizeof(dataType))
Example : -
int a[i] ;
interpreted as :-
a[i] = (base_address_of_a + i * sizeof(int)) ;
