Arrays
Store multiple values of the same type under one name, indexed from zero, contiguous in memory — the foundation for almost every data structure that follows.
An array is a collection of elements of the same type stored as a contiguous sequence of objects. Arrays are useful when a program needs to store multiple related values under one name. For example, instead of writing int mark1 = 80; int mark2 = 75; int mark3 = 92; int mark4 = 88; separately, an array can store them together: int marks[4] = {80, 75, 92, 88}; Each element has an index, and C++ array indexing starts at 0.
Declaring an Array
The basic syntax for declaring an array is type array_name[size]; This reserves storage for a fixed number of elements of the given type.
Declares an array containing five int elements. The elements are not initialized to any particular value by this declaration alone.
The valid indices are 0, 1, 2, 3, 4. There is no valid index 5.
int numbers[5];numbers
|
v
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+
0 1 2 3 4Array Indexing
An individual element is accessed using the [] operator. The general form is array_name[index].
Assigns values into three elements and prints one of them.
numbers[0] is set to 10 numbers[1] is set to 20 numbers[2] is set to 30 numbers[1] is printed, giving output 20
int numbers[5];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
std::cout << numbers[1];Zero-Based Indexing
C++ arrays use zero-based indexing. For int values[5];, the indices map to elements as follows:
The mapping between index and ordinal position for a five-element array.
The last valid index is size - 1. Therefore int values[10]; has valid indices 0 through 9.
Index | Element
0 | First
1 | Second
2 | Third
3 | Fourth
4 | FifthArray Initialization
Initializes all five elements at declaration time using a brace-enclosed initializer list.
The resulting layout of the array in memory, by index.
int numbers[5] = {10, 20, 30, 40, 50};+----+----+----+----+----+
| 10 | 20 | 30 | 40 | 50 |
+----+----+----+----+----+
0 1 2 3 4Partial Initialization
Only the first two elements are given explicit values.
The remaining elements are value-initialized. For an array of int, the remaining elements become 0.
The final contents after partial initialization.
int numbers[5] = {10, 20};+----+----+----+----+----+
| 10 | 20 | 0 | 0 | 0 |
+----+----+----+----+----+Initialize All Elements to Zero
An empty brace initializer value-initializes every element.
All elements are initialized to zero.
This is often preferable to manually writing zeros for every element.
int numbers[5] = {};+---+---+---+---+---+
| 0 | 0 | 0 | 0 | 0 |
+---+---+---+---+---+Let the Compiler Deduce the Array Size
No size is written inside the brackets.
The compiler determines the number of elements (4 here) from the initializer list, so the resulting type is equivalent to int numbers[4];
int numbers[] = {10, 20, 30, 40};Character Arrays
This is simply an array of four char objects.
The four char elements stored in the array.
Character arrays used specifically as C-style strings have additional null-termination rules and are a separate string concept.
char letters[4] = {'A', 'B', 'C', 'D'};+-----+-----+-----+-----+
| 'A' | 'B' | 'C' | 'D' |
+-----+-----+-----+-----+Accessing Array Elements
Reads an element, modifies it, and reads it again.
numbers[2] is 30, so the first line prints 30 numbers[2] is reassigned to 100 the second line prints 100 only the selected element is modified; the others are unchanged
int numbers[4] = {10, 20, 30, 40};
std::cout << numbers[2] << '\n';
numbers[2] = 100;
std::cout << numbers[2] << '\n';Using a for Loop with an Array
Prints every element of the array using an index-based loop.
i=0 accesses numbers[0] i=1 accesses numbers[1] and so on through i=4, which accesses numbers[4] output: 10 20 30 40 50
The loop index corresponds directly to the array index.
int numbers[5] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; ++i)
{
std::cout << numbers[i] << '\n';
}Modifying Elements with a Loop
Doubles every element in place by writing back through the index.
The array's contents after the loop finishes.
int numbers[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; ++i)
{
numbers[i] *= 2;
}+----+----+----+----+----+
| 2 | 4 | 6 | 8 | 10 |
+----+----+----+----+----+Finding the Sum of an Array
Accumulates a running total across all elements.
sum starts at 0 sum += 10 gives 10 sum += 20 gives 30 sum += 30 gives 60 sum += 40 gives 100
int numbers[] = {10, 20, 30, 40};
int sum = 0;
for (int i = 0; i < 4; ++i)
{
sum += numbers[i];
}
std::cout << sum;Finding the Largest Element
Scans the array, keeping track of the biggest value seen so far.
largest starts as numbers[0], which is 25 the loop starts at index 1, comparing each remaining element
45 is greater than the current largest, so largest becomes 45 no later element exceeds 45
Starting with the first element is important because it provides an actual array value as the initial candidate.
int numbers[] = {25, 10, 45, 30, 15};
int largest = numbers[0];
for (int i = 1; i < 5; ++i)
{
if (numbers[i] > largest)
{
largest = numbers[i];
}
}
std::cout << largest;Finding the Smallest Element
Mirrors the largest-element pattern, but keeps the smallest value seen.
smallest starts as numbers[0], which is 25 10 is less than 25, so smallest becomes 10 no later element is smaller than 10 the final value of smallest is 10
int numbers[] = {25, 10, 45, 30, 15};
int smallest = numbers[0];
for (int i = 1; i < 5; ++i)
{
if (numbers[i] < smallest)
{
smallest = numbers[i];
}
}Array Size with sizeof
Computes the element count from two byte-size measurements.
This gives count = 5, because sizeof(numbers) is the size of the entire array and sizeof(numbers[0]) is the size of one element, so number of elements = total array size / element size.
In modern C++, std::size(numbers) from <iterator> is often a clearer way to obtain the number of elements of a built-in array.
int numbers[] = {10, 20, 30, 40, 50};
std::size_t count = sizeof(numbers) / sizeof(numbers[0]);std::size_t count = std::size(numbers);sizeof Does Not Mean Number of Elements
This does not give the number of elements — it is a common point of confusion.
sizeof(numbers) gives the array's size in bytes, not its number of elements. For example, if an array contains five int objects and an int occupies four bytes on a particular implementation, sizeof(numbers) = 20 bytes while number of elements = 5.
std::size_t count = sizeof(numbers);Array Bounds
For int numbers[5];, valid indices are numbers[0] through numbers[4]. numbers[5] is invalid, and so is numbers[-1].
C++ does not perform automatic bounds checking for built-in arrays. Accessing outside the array's valid range results in undefined behavior.
Off-by-One Boundary Errors
Incorrect: uses <= instead of <, so the loop runs one iteration too many.
When i == 5, the code accesses numbers[5], which is outside the array.
Correct: the strict less-than bound stops at the last valid index, 4.
A useful general pattern for iterating any array whose element count is stored in count.
int numbers[5];
for (int i = 0; i <= 5; ++i)
{
std::cout << numbers[i];
}for (int i = 0; i < 5; ++i)
{
std::cout << numbers[i];
}for (std::size_t i = 0; i < count; ++i)
{
// array[i]
}Arrays Are Contiguous
The elements of a built-in array are stored contiguously.
The four elements occupy adjacent memory locations in index order.
There are no gaps inserted between ordinary array elements. This contiguous representation is one reason arrays provide efficient indexed access.
int numbers[4] = {10, 20, 30, 40};
Lower address Higher address
+---------+---------+---------+---------+
| 10 | 20 | 30 | 40 |
+---------+---------+---------+---------+
0 1 2 3Array Access and Indexing
For a built-in array, numbers[i] provides access to the element at index i. Array indexing is closely related to pointer arithmetic, but pointers and arrays are distinct concepts.
For this topic, the important point is: array + index → selected element. The detailed relationship between arrays and pointers belongs to pointer-specific topics.
Multidimensional Arrays
C++ supports arrays whose elements are themselves arrays.
This represents 3 rows by 4 columns.
The conceptual grid layout of a 3x4 matrix.
int matrix[3][4];columns
0 1 2 3
+---+---+---+---+
row 0| | | | |
+---+---+---+---+
row 1| | | | |
+---+---+---+---+
row 2| | | | |
+---+---+---+---+Initializing a Two-Dimensional Array
Nested brace lists initialize each row.
The resulting grid of values.
Access: matrix[0][0] is 1, matrix[0][2] is 3, matrix[1][1] is 5. The first index identifies the row, and the second identifies the column.
int matrix[2][3] =
{
{1, 2, 3},
{4, 5, 6}
};+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+Processing a Two-Dimensional Array
A nested loop visits every element, row by row.
the outer loop selects each row, 0 then 1 the inner loop walks across the columns of that row row 0 prints 1 2 3 row 1 prints 4 5 6 The program's output.
int matrix[2][3] =
{
{1, 2, 3},
{4, 5, 6}
};
for (int row = 0; row < 2; ++row)
{
for (int column = 0; column < 3; ++column)
{
std::cout << matrix[row][column] << ' ';
}
std::cout << '\n';
}1 2 3
4 5 6Three-Dimensional Arrays
A three-dimensional array declaration.
This contains 2 x 3 x 4 = 24 elements, addressed conceptually as data[layer][row][column]. For example, data[1][2][3] accesses one particular element.
int data[2][3][4];General Multidimensional Arrays
General form for declaring an array with any number of dimensions.
The total number of elements is d1 x d2 x d3 x ... . For int values[2][3][5];, the total is 2 x 3 x 5 = 30 elements.
type name[d1][d2][d3]...;Row-Major Storage
For multidimensional built-in arrays, the rightmost dimension varies fastest in the contiguous memory layout.
A 2x3 matrix used to illustrate memory layout.
The conceptual contiguous order is 1 -> 2 -> 3 -> 4 -> 5 -> 6 — the first row is followed by the second row. This layout is commonly called row-major order.
int matrix[2][3] =
{
{1, 2, 3},
{4, 5, 6}
};Arrays of Other Types
Arrays can hold any type, including floating-point values, bools, and user-defined struct types.
The array elements still have the same element type regardless of what that type is.
double values[3] = {1.5, 2.5, 3.5};
bool flags[3] = {true, false, true};
struct Point
{
int x;
int y;
};
Point points[3];const Arrays
Declares an array whose elements cannot be modified.
The elements cannot be modified through the array.
const is useful when the array should be treated as read-only.
const int values[] = {10, 20, 30};values[0] = 100; // ErrorArrays Cannot Be Assigned Directly
Built-in arrays cannot be assigned to one another.
This is invalid — array-to-array assignment with = is not supported for built-in arrays.
If element-wise copying is required, it must be performed explicitly, one element at a time.
For suitable types, standard library facilities can also perform copying.
int a[3] = {1, 2, 3};
int b[3];
b = a; // Errorfor (int i = 0; i < 3; ++i)
{
b[i] = a[i];
}Comparing Built-In Arrays
Built-in arrays do not support direct whole-array equality comparison — a == b is not a content comparison.
To compare contents, compare corresponding elements explicitly.
For modern C++, std::array provides more convenient value semantics, including direct comparison.
bool equal = true;
for (int i = 0; i < 3; ++i)
{
if (a[i] != b[i])
{
equal = false;
break;
}
}Arrays as Function Parameters
When a built-in array is passed to a function, the parameter syntax is adjusted to a pointer parameter.
The array parameter is adjusted to an appropriate pointer parameter.
Therefore, the function does not automatically know the array's number of elements — you normally pass the size separately.
Calling the function with both the array and its element count.
void printArray(int values[], int size)
{
for (int i = 0; i < size; ++i)
{
std::cout << values[i] << ' ';
}
}int numbers[] = {10, 20, 30, 40};
printArray(numbers, 4);Why the Array Size Is Usually Passed Separately
Inside the function, values is treated as a pointer parameter rather than as the original array type.
Therefore, sizeof(values) does not give the size of the caller's array.
A common interface that accepts the array's size as a separate parameter.
void printArray(int values[])
{
// ...
}void printArray(const int values[], std::size_t size)
{
for (std::size_t i = 0; i < size; ++i)
{
std::cout << values[i] << '\n';
}
}Modifying an Array Through a Function
A function can modify elements of a caller's built-in array through an array parameter.
Doubles the caller's array elements in place.
numbers starts as {1, 2, 3} doubleValues receives a pointer-like parameter referring to the same elements each element is multiplied by 2 the original array becomes 2 4 6
This behavior follows from the array parameter adjustment and indirect access to the caller's elements.
void doubleValues(int values[], std::size_t size)
{
for (std::size_t i = 0; i < size; ++i)
{
values[i] *= 2;
}
}
int numbers[] = {1, 2, 3};
doubleValues(numbers, 3);Read-Only Array Parameters
This communicates that the function only reads the elements.
void printArray(const int values[], std::size_t size)
{
for (std::size_t i = 0; i < size; ++i)
{
std::cout << values[i] << ' ';
}
}Built-In Arrays vs std::array
A built-in array.
The equivalent std::array declaration.
A feature-by-feature comparison of the two array kinds.
std::array is a separate standard-library type and is often preferable when you need a fixed-size array with container-like behavior.
int values[3] = {10, 20, 30};#include <array>
std::array<int, 3> values = {10, 20, 30};Feature | Built-in array | std::array
Fixed size | Yes | Yes
.size() | No | Yes
Copy assignment | No | Yes
Standard container interface | No | Yes
operator[] | Yes | Yes
.at() bounds checking | No | Yes
Iterators | Limited language support | YesBest Practices
1. Initialize arrays when practical — prefer int values[5] = {}; over leaving the values unintentionally uninitialized.
2. Use correct, strict bounds — for (std::size_t i = 0; i < size; ++i), never <=, since the valid index range is always 0 through size - 1.
3. Keep the size associated with the array — when passing built-in arrays to functions, pass the element count explicitly, since a function receiving an array parameter only sees a pointer and cannot recover the caller's array size from sizeof.
4. Use const for read-only access.
5. Consider std::array when you need a fixed-size array with standard-container functionality.
6. Avoid unnecessary multidimensional complexity — use dimensions that clearly represent the data being modeled.
7. Never assign one built-in array to another with = — copy elements explicitly in a loop, or use std::array/std::vector, which do support assignment and comparison directly.
void print(const int values[], std::size_t size);std::array<int, 5> values{};Complete Example
A complete program combining declaration, size deduction, a read-only print function, and a largest-element search function.
values holds {25, 10, 45, 30, 15} size is computed with std::size(values), giving 5 printArray prints every element findLargest scans the array and returns 45 the program prints the array and then the largest value The program's output.
#include <iostream>
#include <cstddef>
void printArray(const int values[], std::size_t size)
{
for (std::size_t i = 0; i < size; ++i)
{
std::cout << values[i] << ' ';
}
std::cout << '\n';
}
int findLargest(const int values[], std::size_t size)
{
int largest = values[0];
for (std::size_t i = 1; i < size; ++i)
{
if (values[i] > largest)
{
largest = values[i];
}
}
return largest;
}
int main()
{
int values[] = {25, 10, 45, 30, 15};
const std::size_t size = std::size(values);
printArray(values, size);
int largest = findLargest(values, size);
std::cout << "Largest: " << largest << '\n';
return 0;
}25 10 45 30 15
Largest: 45Array Mental Model
Think of a built-in array as a fixed sequence of same-type objects.
A one-dimensional array as a flat sequence of elements.
A two-dimensional array as a grid, indexed by row and column.
The core operation is array[index] or, for multiple dimensions, array[index1][index2]...
Array
|
v
+----+----+----+----+----+
| E0 | E1 | E2 | E3 | E4 |
+----+----+----+----+----+
0 1 2 3 4matrix
|
v
+----+----+----+
| 00 | 01 | 02 |
+----+----+----+
| 10 | 11 | 12 |
+----+----+----+
| 20 | 21 | 22 |
+----+----+----+
[row][column]Quick Reference
A quick-reference table summarizing common array operations from this topic.
For int scores[8];, what is the range of valid indices, and what happens if you access scores[8]?
The valid indices are 0 through 7 (size - 1). scores[8] is out of bounds; C++ performs no automatic bounds checking for built-in arrays, so accessing it is undefined behavior.
Given int values[] = {10, 20, 30, 40, 50}; and an int on this platform occupying 4 bytes, what does sizeof(values) return, and how do you compute the number of elements from it?
sizeof(values) returns 20 (the total byte size of the array, not the element count). The element count is sizeof(values) / sizeof(values[0]), which is 20 / 4 = 5. std::size(values) is a clearer modern alternative.
Why does void printArray(int values[]) inside the function not know how many elements the caller's array has, even though the caller declared int numbers[10];?
When an array is passed to a function, the parameter is adjusted to a pointer to the element type, not the original array type. Inside the function, sizeof(values) gives the size of a pointer, not the array, so the element count must be passed as a separate parameter.
Why is int b[3]; b = a; invalid for two built-in int arrays a and b of the same size, and what must you do instead to copy a's contents into b?
Built-in arrays do not support direct assignment with =. You must copy element-by-element in a loop, such as for (int i = 0; i < 3; ++i) { b[i] = a[i]; }, or use a type like std::array or std::vector that supports assignment directly.
In row-major storage for int matrix[2][3] = {{1,2,3},{4,5,6}};, in what contiguous order are the six elements actually laid out in memory, and which index (row or column) varies fastest?
The contiguous order is 1, 2, 3, 4, 5, 6 — the first row followed by the second row. The rightmost dimension (the column index) varies fastest.
What is the problem with this loop, and what value does numbers[4] hold when printed (assuming the undefined-behavior write to numbers[5] does not corrupt numbers[4] in this run)?
The loop condition uses <= instead of <, so when i == 5 the code writes to numbers[5], which is outside the array's valid range (0-4) and is undefined behavior. Ignoring that fault, numbers[4] was assigned 4 * 10 = 40 during the i == 4 iteration, so it prints 40 — but the program's behavior as a whole is not guaranteed because of the out-of-bounds write.
Write a function named sumArray that takes a const int array and its size (as std::size_t) and returns the sum of all its elements. Then call it on int values[] = {5, 15, 25, 35}; and print the result.
The function iterates from 0 up to (but not including) size, accumulating each element into sum. For {5, 15, 25, 35}, sum becomes 5, then 20, then 45, then 80. The program prints 80.
Trace through the nested loops. What value does total hold at the end, and in what order are the elements visited?
The elements are visited in row-major order: matrix[0][0]=2, matrix[0][1]=4, matrix[0][2]=6, matrix[1][0]=1, matrix[1][1]=3, matrix[1][2]=5. Summing them: 2+4+6+1+3+5 = 21. total is 21.
Write a function named doubleAll that takes an int array and its size (as std::size_t), and multiplies every element by 2 in place (no return value). Then declare int nums[] = {3, 6, 9}; call doubleAll on it, and print the three elements.
Because array parameters decay to pointers, doubleAll modifies the caller's original array elements directly. nums becomes {6, 12, 18}, and the printing loop outputs 6 12 18.
Operation | Example
Declare | int values[5];
Initialize | int values[5] = {1, 2, 3, 4, 5};
Deduce size | int values[] = {1, 2, 3};
Zero initialize | int values[5] = {};
Access | values[2]
Modify | values[2] = 100;
2D array | int matrix[3][4];
Array size | std::size(values)
Total byte size | sizeof(values)
Read-only parameter | const int values[]
Fixed-size standard array | std::array<int, 5>int numbers[5];
for (int i = 0; i <= 5; ++i)
{
numbers[i] = i * 10;
}
std::cout << numbers[4];int matrix[2][3] =
{
{2, 4, 6},
{1, 3, 5}
};
int total = 0;
for (int row = 0; row < 2; ++row)
{
for (int column = 0; column < 3; ++column)
{
total += matrix[row][column];
}
}
std::cout << total;