One-Dimensional Arrays in C++
A one-dimensional array stores a sequence of related values under one name. It is useful when a program must work with many values of the same type, such as marks, ages, prices, or measurements. Instead of creating a separate variable for every value, an array organizes them into numbered positions that can be processed systematically.
Why Do We Need Arrays?
Suppose five marks must be stored and added. Without an array, the program needs five separate variables and must mention every variable explicitly while calculating the total.
#include <iostream>int main() { int marks1 = 78; int marks2 = 85; int marks3 = 91; int marks4 = 66; int marks5 = 88; std::cout << marks1 + marks2 + marks3 + marks4 + marks5; return 0;}This works for five values, but it does not scale. Managing hundreds or thousands of separately named variables would make the program repetitive and difficult to maintain. The values share an important pattern: all of them are marks and all of them have the same data type. An array captures that pattern.
Declaring and Accessing an Array
The same five marks can be stored in a single integer array. The declaration int marks[5] states that marks can contain exactly five integers. The values inside braces initialize its elements in order.
#include <iostream>int main() { int marks[5] = {78, 85, 91, 66, 88}; int sum = marks[0] + marks[1] + marks[2] + marks[3] + marks[4]; std::cout << sum; return 0;}The output is 408. Each value is reached through an index. C++ arrays use zero-based indexing, so the first element is at index 0, not index 1.
marks[0]is78, the first element.marks[1]is85, the second element.marks[2]is91, the third element.marks[3]is66, the fourth element.marks[4]is88, the fifth element.
For an array containing n elements, the valid indexes run from 0 through n - 1. Therefore, an array of size 5 has indexes 0 through 4.
What Defines a One-Dimensional Array?
A one-dimensional array stores a fixed number of values of the same type in contiguous memory. Each part of this definition is significant.
Fixed size: The number of elements is decided when the array is created and cannot later be expanded or reduced.
Same type: An
intarray stores only integers, while adoublearray stores only doubles. A built-in array cannot directly mix unrelated element types.Ordered positions: Every element has a stable numerical index, making it possible to read or update a specific position.
Contiguous memory: The elements occupy consecutive memory locations, one immediately after another.
Contiguous Memory Storage
The address-of operator & reveals where an element is stored. Because adjacent elements are contiguous, the difference between their starting addresses equals the size of one element. On a system where an int occupies four bytes, the addresses of marks[0] and marks[1] differ by four bytes.
#include <iostream>int main() { int marks[5] = {78, 85, 91, 66, 88}; std::cout << &marks[0] << '\n'; std::cout << &marks[1] << '\n'; std::cout << sizeof(int) << '\n'; return 0;}The exact addresses vary from one execution to another and should not be predicted. If the first integer begins at an address ending in 20 and an integer occupies four bytes, it uses four consecutive byte positions; the next integer can begin at the address ending in 24. Although four bytes is common on modern systems, C++ does not require int to have that exact size, which is why sizeof(int) is used to inspect it.
Declaration and Initialization
Declaration Without Initialization
The statement int marks[5]; creates space for five integers but does not provide initial values. For a local built-in array, reading an element before assigning it a value produces undefined behavior. It may appear to print a random or garbage value, but no particular result is guaranteed. Every element must be initialized before it is read.
After an array has already been declared, values are assigned one element at a time. A braced list cannot be assigned to the entire built-in array later.
#include <iostream>int main() { int marks[5]; marks[0] = 6; marks[1] = 5; marks[2] = 9; marks[3] = 7; marks[4] = 8; return 0;}Initialization During Declaration
When an array is created, several valid initialization forms are available:
Full initialization:
int values[5] = {1, 2, 3, 4, 5};supplies one value for every element.Partial initialization:
int values[5] = {1};stores1at index0and zero-initializes all remaining elements.Inferred size:
int scores[] = {7, 8, 9};lets the compiler count the initializers and create an array of size3.Zero initialization:
int zeros[5] = {};initializes all five elements to0.
#include <iostream>int main() { int values[5] = {1, 2, 3, 4, 5}; int partial[5] = {1}; int scores[] = {7, 8, 9}; int zeros[5] = {}; std::cout << values[4] << '\n'; std::cout << partial[4] << '\n'; std::cout << zeros[2] << '\n'; return 0;}This prints 5, 0, and 0. Partial initialization and empty-brace initialization are different from declaring an uninitialized local array: the presence of an initializer causes all unspecified elements to become zero.
Reading and Updating Elements
An element is read by writing the array name followed by its index in square brackets. The same indexed expression can appear on the left side of an assignment to replace a value. Increment, decrement, and arithmetic-assignment operators can also update an element exactly as they update an ordinary variable.
#include <iostream>int main() { int numbers[4] = {10, 20, 30, 40}; numbers[2] = 100; numbers[0]++; std::cout << numbers[0] << ' '; std::cout << numbers[2] << '\n'; return 0;}After the updates, the array is {11, 20, 100, 40}. The old values 10 and 30 have been replaced at their respective positions.
Traversing an Array
Traversal means visiting the elements one by one. For a five-element array, writing five separate output statements works, but it repeats the same operation while only the index changes.
#include <iostream>int main() { int marks[5] = {1, 2, 3, 4, 5}; std::cout << marks[0] << '\n'; std::cout << marks[1] << '\n'; std::cout << marks[2] << '\n'; std::cout << marks[3] << '\n'; std::cout << marks[4] << '\n'; return 0;}A for loop expresses the pattern directly. The loop begins at index 0, continues while the index is less than the size, and increments the index after each visit. For size 5, the loop therefore uses 0, 1, 2, 3, 4.
#include <iostream>int main() { int marks[5] = {1, 2, 3, 4, 5}; for (int i = 0; i < 5; i++) { std::cout << marks[i] << '\n'; } return 0;}The condition i < 5 prevents the loop from reaching index 5, which lies outside the array. In general, traversal runs from index 0 while i < n, so the final visited index is n - 1.
Taking Array Input
Consider an input whose first value is n, followed by n marks. If n is 7, the next seven values might be 7 8 4 5 6 2 1. Each mark must first be stored and then printed on a separate line.
If the values only had to be printed immediately, a single ordinary variable could receive and print each value inside a loop. The requirement to retain all values changes the problem: storage is needed, so an array is appropriate.
Building the Index Logic
A loop may count from 1 through n and store each value at marks[i - 1]. When i is 1, the destination is index 0; when i is n, the destination is index n - 1. However, starting the loop at 0 is simpler because the loop variable can be used directly as the array index.
#include <iostream>int main() { constexpr int MAX_MARKS = 100000; int marks[MAX_MARKS]; int n; std::cin >> n; for (int i = 0; i < n; i++) { std::cin >> marks[i]; } for (int i = 0; i < n; i++) { std::cout << marks[i] << '\n'; } return 0;}The first loop fills the array index by index. The second loop revisits the same valid range and prints the stored values.
Built-in array sizes in standard C++ must be compile-time constants. Some compilers accept int marks[n]; as an extension, but it is not portable standard C++. When the required capacity is known only at runtime, std::vector<int> is the standard resizable alternative; built-in arrays themselves remain fixed-size.
Staying Within Array Boundaries
For an array of size 5, only indexes 0 through 4 are valid. Accessing marks[-1], marks[5], or any other position outside that interval is out-of-bounds access.
With built-in C++ arrays, out-of-bounds access causes undefined behavior. The program might print an apparently random value, corrupt other data, crash, or seem to work temporarily. C++ does not guarantee an automatic “index out of bounds” error for a built-in array, although debugging tools, sanitizers, or checked containers may detect the mistake. Loops should therefore use the boundary pattern 0 <= i && i < n.
Range-Based For Loops
A range-based for loop visits every element without manually writing an index. Its behavior depends on whether the loop variable is a value or a reference.
Iteration by Value
In for (int value : numbers), value is a copy of the current element. Changing the copy does not change the array.
#include <iostream>int main() { int numbers[3] = {10, 20, 30}; for (int value : numbers) { value = value + 5; } for (int value : numbers) { std::cout << value << ' '; } return 0;}The output remains 10 20 30 because only temporary copies were increased.
Iteration by Reference
In for (int &value : numbers), value is another name for the current array element. Updating the reference updates the original array.
#include <iostream>int main() { int numbers[3] = {10, 20, 30}; for (int &value : numbers) { value = value + 5; } for (int value : numbers) { std::cout << value << ' '; } return 0;}The array becomes {15, 25, 35}. If a range-based loop only needs to read large elements, const references can avoid copies while preventing modification, although copying an int is inexpensive.
Passing an Array to a Function
An array can be supplied to a function by passing its name. The function parameter is commonly written as int numbers[], and the array size is passed separately because the function cannot determine the number of elements from that parameter alone.
The parameter name does not have to match the caller's variable name. An array named marks in main() can be received as numbers in another function. Both provide access to the same underlying elements.
#include <iostream>void printArray(int numbers[], int n) { numbers[0] = 8; for (int i = 0; i < n; i++) { std::cout << numbers[i] << ' '; } std::cout << '\n';}int main() { int marks[5] = {1, 2, 3, 4, 5}; printArray(marks, 5); std::cout << marks[0] << '\n'; return 0;}The function changes the first element from 1 to 8. After the call, marks[0] in main() is also 8. In a function parameter, int numbers[] is adjusted by the language to a pointer parameter, so the function receives access to the original array elements rather than a complete element-by-element copy.
Read-Only Array Parameters
If a function only needs to inspect an array, adding const prevents accidental modification. The function can read and print each element, but an assignment such as numbers[0] = 8; would be rejected by the compiler.
#include <iostream>void printArray(const int numbers[], int n) { for (int i = 0; i < n; i++) { std::cout << numbers[i] << ' '; } std::cout << '\n';}int main() { int marks[5] = {1, 2, 3, 4, 5}; printArray(marks, 5); return 0;}Use a non-const array parameter when modification is an intended part of the function. Use a const array parameter when the function should be read-only. This makes the function's purpose clearer and lets the compiler protect the original data from unintended changes.
Summary
A one-dimensional array groups a fixed number of same-type values under one name.
Its elements occupy contiguous memory and are accessed through zero-based indexes.
For an array of size
n, the valid index range is0throughn - 1.Arrays can be fully initialized, partially initialized, zero-initialized, or initialized with an inferred size.
Indexed loops support input, output, updates, and complete traversal.
Range-based loops iterate by value when copies are required and by reference when original elements must be modified.
Array parameters provide access to the original elements;
constshould be added when a function must only read them.
Be the first to add a comment.