Fundamentals
C++ arrays: the whole picture
Short answer: int a[5] reserves five consecutive int slots and names them a[0] … a[4]. The size is fixed at compile time and C++ does not check your indices at runtime.
Memory is a row, not a grid
An array is one contiguous block. a[3] is not a lookup with a name — it is "start of the block, plus three elements' worth of bytes". That is why indexing is O(1): one multiplication, one add.
#include <iostream>
using namespace std;
int main() {
int a[5] = {10, 20, 30, 40, 50};
cout << "first: " << a[0] << endl;
cout << "third: " << a[2] << endl;
cout << "last: " << a[4] << endl;
return 0;
}
There is no a[5]. Writing it compiles, runs, and reads whatever happens to sit next in memory — that is undefined behaviour, not an error message.
Why zero?
Because the index is an offset. The first element is zero slots away from the start of the block. Languages that start at 1 have to subtract before every access; C++ makes that subtraction free by writing it into your code.
Sizing: pick a ceiling, not the exact count
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int a[100]; // declare a ceiling
for (int i = 0; i < n; i++) cin >> a[i];
cout << "read " << n << " values" << endl;
return 0;
}
You cannot resize a C++ array. In real code you either declare a generous ceiling (as here), or use std::vector which grows. Compare them in vector vs array.
The three patterns worth memorising
1. Sum — initialise the accumulator to zero.
#include <iostream>
using namespace std;
int main() {
int a[5] = {1, 2, 3, 4, 5};
int sum = 0;
for (int i = 0; i < 5; i++) sum += a[i];
cout << sum << endl; // 15
return 0;
}
2. Maximum — seed with the first element, never with zero.
#include <iostream>
using namespace std;
int main() {
int a[4] = {-9, -3, -7, -1};
int best = a[0];
for (int i = 1; i < 4; i++) {
if (a[i] > best) best = a[i];
}
cout << best << endl; // -1, not 0
return 0;
}
3. Count — one counter per category.
#include <iostream>
using namespace std;
int main() {
int a[6] = {4, 7, 10, 3, 8, 1};
int even = 0, odd = 0;
for (int i = 0; i < 6; i++) {
if (a[i] % 2 == 0) even++;
else odd++;
}
cout << "even " << even << ", odd " << odd << endl;
return 0;
}
Two-dimensional arrays are rows of rows
#include <iostream>
using namespace std;
int main() {
int g[3][2] = {{1, 2}, {3, 4}, {5, 6}};
for (int r = 0; r < 3; r++) {
for (int c = 0; c < 2; c++) {
cout << g[r][c] << " ";
}
cout << endl;
}
return 0;
}
The first index is the row, always. Reversing them silently transposes your data — the bug behind Matrix Transpose exercises.
Bugs that do not announce themselves
- Off-by-one.
i <= nreadsa[n], one past the end. No crash guaranteed, no warning. - Too small a declaration.
int a[10]with 11 values overwrites neighbouring memory. - Uninitialised accumulator.
int sum; sum += a[i];starts from garbage. - Seeding a max with 0. Works for positive input, fails for all-negative — the test that catches it is in Array Maximum.
Practice: Array Maximum, Even and Odd Count, Sum a Matrix. Next: Big O notation explains why a nested loop over this array is O(n²).