A Fixed-Size Row of Values
An array is a contiguous block of memory holding a fixed number of values of the same type. Where a single int stores one number, an int array stores many of them back to back, each reachable by an integer index.
You declare one by giving the element type, a name, and a size in square brackets. Add a brace-enclosed list to fill it in:
Indexing is zero-based: the first element is scores[0], and an array of size 4 has valid indices 0 through 3. The size must be a compile-time constant - you cannot write int n = readInput(); int a[n]; in standard C++ (that's a non-portable extension). When you need a size decided at runtime, reach for a vector instead.
Initializing Arrays
You have a few ways to fill an array, and a couple of shortcuts worth knowing:
The gotcha to internalize: when you provide fewer initializers than the size, the leftovers are value-initialized (zero for numeric types), not left as garbage. But an array with no initializer at all - int e[4]; declared as a local - contains indeterminate values, and reading them before assigning is undefined behavior.
Looping Over an Array
Because elements are stored contiguously, you walk an array with a plain index loop. To stay in bounds, drive the loop with the array's real length rather than a hardcoded number:
sizeof(scores) is the total byte count of the whole array; dividing by sizeof(scores[0]) (one element's size) yields the element count. Since C++17 there's a cleaner spelling, std::size(scores), that reads better and refuses to compile if you accidentally hand it a pointer. Even simpler when you only need the values: a range-based for skips the index math entirely.
The Out-of-Bounds Trap
C++ does no bounds checking on arr[i]. Indexing past the last element doesn't throw or warn - it reads or writes whatever memory happens to sit there. This is the single most common array bug, and it's classic undefined behavior:
int a[3] = {1, 2, 3};
a[3] = 99; // OOPS - valid indices are 0..2, not 3
cout << a[5]; // garbage, crash, or corruption - undefined behavior
The off-by-one usually hides in a loop condition. Writing i <= n instead of i < n runs one step too far and touches arr[n], which doesn't exist:
for (int i = 0; i <= n; i++) // BUG: when i == n, arr[i] is out of bounds
cout << arr[i];
The fix is the discipline of the previous section: loop with i < size, never <=, and compute the size from the array rather than retyping a literal that drifts out of sync when you add an element.
Array Decay: The Hidden Pointer
The trickiest array behavior in C++ is decay: when you pass an array to a function, it silently converts to a pointer to its first element. The size information is lost, so sizeof inside the function measures the pointer, not the array.
Note that int arr[] and int* arr are identical as function parameters - the brackets are cosmetic. Because the count is gone, you must pass the length alongside the array yourself:
int sum(const int* arr, int n) {
int total = 0;
for (int i = 0; i < n; i++) total += arr[i];
return total;
}
This "pass a pointer and a length, and pray they match" pattern is exactly the friction that pushes most C++ code toward std::array and std::vector, which carry their own size and never decay.
A Quick Word on Multidimensional Arrays
You can nest the brackets to make a grid. A 2D array is really an array of arrays, laid out row by row in memory:
Index it as grid[row][col]. The same bounds and decay caveats apply - and they get worse, since passing a 2D array to a function requires spelling out every dimension except the first (void f(int g[][3])). For anything beyond a small fixed grid, a vector of vectors is far less error-prone.
Next: Vector
Raw arrays are fast and predictable, but their fixed size, lack of bounds safety, and decay-to-pointer behavior make them awkward for everyday code. Next we'll meet std::vector - a resizable array that grows on demand, remembers its own size, and plugs straight into the STL algorithms, giving you almost everything arrays offer with far fewer ways to shoot yourself in the foot.
Frequently Asked Questions
How do you declare and initialize an array in C++?
Write the element type, a name, and the size in square brackets, then optionally a brace list: int scores[4] = {90, 75, 100, 60};. You can omit the size when you supply initializers - int scores[] = {90, 75, 100, 60}; lets the compiler count them for you.
How do you get the length of an array in C++?
For a real array still in scope, use std::size(arr) (C++17) or sizeof(arr) / sizeof(arr[0]). This does not work once the array has decayed to a pointer (e.g. inside a function that took int arr[]), where sizeof gives the pointer's size, not the array's.
What happens if you access an array out of bounds in C++?
It's undefined behavior. C++ does no bounds checking on arr[i], so reading or writing past the end might crash, return garbage, or silently corrupt nearby memory. Always keep your index in the range 0 to size - 1.