Содержание
В прошлой статье мы разобрали циклы while, do while и for и научились повторять действия, не копируя код.
Но пока все наши данные хранятся в отдельных переменных: одно число — одна переменная. А что, если чисел пять, сто или тысяча и работать с ними нужно все вместе: вывести в обратном порядке, найти наибольшее, посчитать сумму? Для этого в C++ есть массивы.
В этой статье мы разберём одномерные статические массивы в C++: как их объявлять и инициализировать, как обращаться к элементам по индексу, как вводить и выводить массив циклом for и как решать типовые задачи на массивы. А ещё — самую частую ошибку новичков: выход за границы массива. Динамической памяти здесь не будет — о ней мы поговорим в следующих уроках.
После этой статьи Вы сможете:
- объяснить, что такое массив, элемент, индекс и размер массива;
- объявлять и инициализировать массивы в C++;
- обращаться к элементам массива по индексу и изменять их;
- узнавать размер массива с помощью
std::sizeиsizeof; - вводить и выводить массив с помощью цикла
for; - решать типовые задачи: сумма, максимум, подсчёт и поиск элементов, вывод в обратном порядке;
- замечать и не допускать выход за границы массива.
Зачем нужны массивы
Начнём с задачи: с клавиатуры вводятся оценки пяти учеников, и их нужно вывести на экран в обратном порядке. С тем, что мы уже знаем, решение выглядит так:
#include <iostream>
int main() {
int a1, a2, a3, a4, a5;
std::cin >> a1 >> a2 >> a3 >> a4 >> a5;
std::cout << a5 << " " << a4 << " " << a3 << " " << a2 << " " << a1 << "\n";
return 0;
}
5 4 3 5 2
2 5 3 4 5
Программа работает, но что, если учеников не пять, а 125 или 1000? Не будем же мы создавать тысячу переменных, а потом тысячу раз перечислять их в std::cin и std::cout. А если количество учеников вводит пользователь, мы даже не знаем заранее, сколько переменных понадобится.
Циклы здесь сами по себе не помогут: числа нужно сначала все считать, а потом вывести в другом порядке. Значит, их нужно где-то хранить — в «ящике», по которому можно ходить в любом порядке: от первого к последнему, задом наперёд, через один. Такой ящик и есть массив.
Что такое массив в C++
Массив в C++ — это пронумерованный набор элементов одного типа с общим именем.
Массив можно представить как ящик с названием, например numbers, в котором лежат переменные. Только у каждой из них нет собственного имени вроде a, b или c — вместо имени у неё есть номер внутри ящика.
Если элементы массива идут в один ряд и у каждого из них один номер, массив называют одномерным. Бывают и двумерные массивы — таблицы из строк и столбцов, — их мы разберём в следующем уроке.
Запомним три термина:
- элемент — одна ячейка массива, одно хранящееся в нём значение;
- индекс — номер элемента в массиве;
- размер — количество элементов в массиве. Если размер массива 10, значит, в нём 10 элементов.
Как объявить массив в C++
Массив в C++ объявляется так:
int data[5];
Разберём, из чего состоит это объявление:
int— тип данных элементов массива;data— имя массива. Его выбирают по тем же правилам, что и имя переменной:data,data2,student_marks;[5]— размер массива, то есть количество элементов.
Важно: все элементы массива в C++ имеют один и тот же тип. Массив может хранить только int, только double, только char или только bool. Создать массив, в котором лежат, например, пять int, три double и два char, нельзя.
Как массив выглядит в памяти
Когда мы объявляем int data[5];, в оперативной памяти компьютера появляются пять элементов типа int, расположенных друг за другом. Массивы принято изображать как ряд пронумерованных ячеек: под каждой ячейкой подписан её индекс — от 0 до 4. Так массивы рисуют во всех учебниках и на разборах задач.
Мы не сказали, чему равны элементы, поэтому в них лежит мусор — значения, которые остались в этой памяти до запуска программы. Это может быть что угодно: 0, −1, миллиард, 35. При каждом новом запуске там могут оказаться другие числа. Подробнее о мусоре и неопределённом поведении — в статье «Неинициализированная переменная и неопределённое поведение в C++».
Инициализация массива в C++
Элементы массива можно задать сразу при объявлении — перечислить их в фигурных скобках:
int data[5] = {1, 2, 3, 4, 5};
Знак = можно не писать: запись int data[5]{1, 2, 3, 4, 5}; делает то же самое.
Если значений в фигурных скобках меньше, чем элементов, первые элементы получат перечисленные значения, а остальные гарантированно станут нулями:
int data[5] = {1, 2}; // 1 2 0 0 0
Отсюда удобный способ получить массив из одних нулей — пустые фигурные скобки:
int zeros[5] = {}; // 0 0 0 0 0
Если не указать размер, компилятор посчитает его сам по количеству значений:
int data[] = {7, 8, 9}; // размер 3
А вот положить в массив больше значений, чем в нём элементов, нельзя — программа не скомпилируется:
int data[2] = {1, 2, 3}; // ошибка компиляции: значений больше, чем элементов
| Объявление | Что лежит в массиве |
|---|---|
int data[5]; | мусор |
int data[5] = {1, 2, 3, 4, 5}; | 1 2 3 4 5 |
int data[5] = {1, 2}; | 1 2 0 0 0 |
int data[5] = {}; | 0 0 0 0 0 |
int data[] = {7, 8, 9}; | 7 8 9, размер 3 |
int data[2] = {1, 2, 3}; | ошибка компиляции |
Размер массива известен на этапе компиляции
Размер массива должен быть известен уже на этапе компиляции — до того, как программа будет запущена. Поэтому в квадратных скобках можно писать литерал или константу:
int a[5]; // можно: 5 — литерал
const int kSize = 5;
int b[kSize]; // можно: константа известна на этапе компиляции
А так делать нельзя:
int n;
std::cin >> n;
int c[n]; // нельзя: n известно только во время работы программы
Значение n появляется только в рантайме — во время работы программы, когда пользователь его ввёл. На этапе компиляции оно неизвестно.
И ещё одно важное правило: изменить размер массива после объявления нельзя. Если массив объявлен на 5 элементов, сделать из него массив на 3, 100 или 125 элементов не получится — придётся создать новый массив и переложить в него элементы.
Как же тогда быть, если количество элементов вводит пользователь? Об этом — чуть ниже, в разделе про массив «с запасом».
Как узнать размер массива в C++
Размер массива известен компилятору, поэтому его можно получить прямо в коде, а не держать в голове. Начиная с C++17 для этого есть функция std::size из заголовка <iterator>:
#include <iostream>
#include <iterator>
int main() {
int data[] = {7, 3, 9, 1, 5};
const int n = std::size(data);
std::cout << "Элементов: " << n << "\n";
for (int i = 0; i < n; i++) {
std::cout << data[i] << " ";
}
std::cout << "\n";
return 0;
}
Элементов: 5
7 3 9 1 5
Размер мы сохранили в константу n и используем её в условии цикла. Если добавить в фигурные скобки ещё один элемент, размер пересчитается сам — ни объявление, ни цикл править не придётся.
В задачах и в старом коде часто встречается другой способ — через оператор sizeof. Он возвращает размер в байтах: всего массива или одного его элемента. Если разделить первое на второе, получится количество элементов:
#include <iostream>
int main() {
int data[5];
std::cout << sizeof(data) << "\n"; // размер всего массива в байтах
std::cout << sizeof(data[0]) << "\n"; // размер одного элемента
std::cout << sizeof(data) / sizeof(data[0]) << "\n"; // количество элементов
return 0;
}
20
4
5
На большинстве компьютеров int занимает 4 байта, поэтому массив из пяти элементов занимает 20 байт, а 20 / 4 = 5.
Обращение к элементу массива по индексу
Чтобы обратиться к элементу массива, пишут имя массива, а в квадратных скобках — индекс элемента:
#include <iostream>
int main() {
int data[5] = {10, 20, 30, 40, 50};
std::cout << data[0] << "\n"; // первый элемент
std::cout << data[2] << "\n"; // третий элемент
std::cout << data[4] << "\n"; // последний элемент
return 0;
}
10
30
50
data[0] — это первый элемент, 10. data[2] — третий элемент, 30: «третий по-человечески» элемент имеет индекс 2. А последний элемент массива из пяти элементов — data[4].
Элементы массива можно не только читать, но и изменять — как обычные переменные:
data[2] = 99; // теперь массив: 10 20 99 40 50
В квадратных скобках не обязательно писать число. Индексом может быть переменная или целое выражение:
int i = 2;
std::cout << data[i] << "\n"; // data[2]
std::cout << data[i + 1] << "\n"; // data[3]
Именно это и позволяет перебирать элементы массива в цикле.
Ввод и вывод массива циклом for
Какой цикл лучше всего подходит для работы с массивом? Размер массива — константа, известная заранее, значит, мы точно знаем, сколько элементов нужно перебрать. А когда количество повторений известно, удобнее всего цикл for.
Выведем на экран все элементы массива:
#include <iostream>
int main() {
int data[3] = {10, 20, 30};
for (int i = 0; i < 3; i++) {
std::cout << data[i] << " ";
}
std::cout << "\n";
return 0;
}
10 20 30
Счётчик i принимает значения 0, 1, 2 — ровно индексы элементов массива. Цикл идёт от 0 до 3 не включительно, потому что в массиве три элемента и индекс последнего — 2.
i | i < 3 | Вывод |
|---|---|---|
| 0 | true | 10 |
| 1 | true | 20 |
| 2 | true | 30 |
| 3 | false | цикл завершён |
Обратите внимание: на последней проверке i равно 3 — счётчик «смотрит» уже за пределы массива. Но условие 3 < 3 ложно, новая итерация не начинается, и к несуществующему элементу data[3] мы не обращаемся. Цикл написан правильно.
Массив «с запасом»
В задачах часто пишут так: «сначала вводится количество чисел n, а затем сами числа; чисел не больше 100». Размер массива с клавиатуры ввести нельзя, но ограничение нам известно. В таком случае объявляют массив максимально возможного размера и работают только с его частью:
#include <iostream>
int main() {
const int SIZE = 100;
double arr[SIZE] = {3.1415, 2.17, 36.6};
int n = 3; // сколько элементов используем на самом деле
for (int i = n - 1; i >= 0; i--) {
std::cout << arr[i] << " ";
}
std::cout << "\n";
return 0;
}
36.6 2.17 3.1415
Физически в памяти лежат все 100 элементов типа double — это 100 × 8 = 800 байт. Первые три мы задали, остальные 97 стали нулями, но они нам не интересны: мы выделили их с запасом, вдруг пользователю понадобится больше, и работаем только с первыми n элементами.
Цикл в этом примере выводит элементы задом наперёд: начинаем с индекса n - 1 — последнего используемого элемента — и идём до 0 включительно с шагом −1. Ту же задачу можно решить и обычным циклом от 0 до n, если поменять формулу индекса:
for (int i = 0; i < n; i++) {
std::cout << arr[n - 1 - i] << " ";
}
При i = 0 формула n - 1 - i даёт 2 — последний элемент, при i = 1 — 1, при i = 2 — 0. Можно менять либо сам цикл, либо формулу в квадратных скобках — результат одинаковый.
Ввод массива с клавиатуры
Считать весь массив одной командой std::cin >> data; нельзя. Элементы вводят по одному — в цикле:
#include <iostream>
int main() {
int data[5];
for (int i = 0; i < 5; i++) {
std::cin >> data[i];
}
for (int i = 0; i < 5; i++) {
std::cout << data[i] << " ";
}
std::cout << "\n";
return 0;
}
7 3 9 1 5
7 3 9 1 5
Сначала в массиве мусор. Пусть пользователь вводит числа 7, 3, 9, 1, 5. При i = 0 первое число, 7, попадает в data[0], при i = 1 тройка попадает в data[1] и так далее — массив заполняется поэлементно.
i | Вводим | Массив после шага |
|---|---|---|
| — | — | ? ? ? ? ? |
| 0 | 7 | 7 ? ? ? ? |
| 1 | 3 | 7 3 ? ? ? |
| 2 | 9 | 7 3 9 ? ? |
| 3 | 1 | 7 3 9 1 ? |
| 4 | 5 | 7 3 9 1 5 |
Типовые задачи на массивы
Большинство задач на массивы устроено по одной схеме: пробегаем по всем элементам — от первого к последнему или от последнего к первому — и что-то делаем с каждым: выводим, суммируем, сравниваем. Разберём самые частые такие задачи. Во всех примерах сначала вводится количество элементов n (не больше 100), а затем сами элементы.
Сумма элементов массива
#include <iostream>
int main() {
const int SIZE = 100;
int data[SIZE];
int n;
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cin >> data[i];
}
int sum = 0;
for (int i = 0; i < n; i++) {
sum += data[i];
}
std::cout << sum << "\n";
return 0;
}
5
7 3 9 1 5
25
Переменную sum обнуляем до цикла и на каждой итерации прибавляем к ней очередной элемент: 0 + 7 = 7, 7 + 3 = 10, 10 + 9 = 19, 19 + 1 = 20, 20 + 5 = 25.
Дальше будем показывать только ту часть программы, которая идёт после ввода массива.
Максимальный элемент массива и его индекс
Чтобы найти максимум, запоминаем индекс наибольшего элемента среди уже просмотренных. Начинаем с нулевого элемента и сравниваем с ним все остальные:
int iMax = 0;
for (int i = 1; i < n; i++) {
if (data[i] > data[iMax]) {
iMax = i;
}
}
std::cout << data[iMax] << " " << iMax << "\n";
5
7 3 9 1 5
9 2
Максимум — 9, он стоит на позиции с индексом 2. Минимум ищут точно так же, только знак сравнения другой.
Количество элементов по условию
Сколько учеников получили пятёрку? Заводим счётчик и увеличиваем его, когда элемент подходит под условие:
int count = 0;
for (int i = 0; i < n; i++) {
if (data[i] == 5) {
count++;
}
}
std::cout << count << "\n";
6
5 4 5 3 5 2
3
Поиск элемента в массиве
Есть ли в массиве число x, и если есть, то где оно встречается впервые? Идём по массиву и, как только нашли, останавливаемся с помощью break:
int x;
std::cin >> x;
int pos = -1; // -1 значит «не нашли»
for (int i = 0; i < n; i++) {
if (data[i] == x) {
pos = i;
break;
}
}
std::cout << pos << "\n";
5
7 3 9 1 5
9
2
Если числа в массиве нет, pos так и останется равным −1. Индекса −1 у массива не бывает, поэтому его удобно использовать как признак «элемент не найден».
Вывод массива в обратном порядке
Вернёмся к задаче из начала статьи и решим её правильно — с массивом:
#include <iostream>
int main() {
int marks[5];
for (int i = 0; i < 5; i++) {
std::cin >> marks[i];
}
for (int i = 4; i >= 0; i--) {
std::cout << marks[i] << " ";
}
std::cout << "\n";
return 0;
}
5 4 3 5 2
2 5 3 4 5
Первый цикл заполняет массив, второй выводит его, начиная с последнего элемента — индекса 4 — и уменьшая i до нуля. Чтобы обработать не 5, а 125 оценок, достаточно поменять размер массива и границы циклов, а лучше — завести для размера константу и использовать её везде.
Задачи такого типа ждут Вас и в контесте к этому уроку, а ещё больше задач с разбором — в статье «Задачи по C++ для начинающих с решениями».
Выход за границы массива
Что будет, если в массиве из пяти элементов обратиться к элементу data[5]? Такого элемента нет: индексы заканчиваются на 4, а ячейка «после последней» массиву не принадлежит.
Разве компилятор не заметит такую ошибку? Нет: компилятор не проверяет индексы. Индексом может быть переменная, значение которой становится известно только во время работы программы, например введённое с клавиатуры. Размер массива должен быть известен на этапе компиляции, а индексы — нет.
Если программа обратится за границы массива, она прочитает или испортит чужую память — или память другой переменной своей же программы. Такое поведение называется неопределённым (undefined behavior): программа может сделать всё что угодно. Например:
- вывести мусор;
- испортить значения других переменных;
- аварийно завершиться: операционная система может заметить, что программа обращается к чужой памяти, и остановить её — это знаменитая ошибка Segmentation fault;
- сработать «как надо».
Чаще всего за границы массива выходят из-за невнимательно написанного условия, когда цикл делает лишнюю итерацию:
int data[5];
for (int i = 0; i <= 5; i++) { // ошибка: при i = 5 выходим за границы
std::cin >> data[i];
}
Правильно — идти от 0 до размера массива не включительно:
int data[5];
for (int i = 0; i < 5; i++) {
std::cin >> data[i];
}
В массиве из n элементов индексы всегда идут от 0 до n - 1. Если в задаче цикл начинается не с 0 или заканчивается не на n - 1, это нестандартный случай, и с границами нужно быть особенно аккуратным.
Подведём итоги
В этой статье Вы познакомились с одномерными статическими массивами — первым способом хранить в программе много значений сразу.
Главное, что нужно запомнить:
- массив — это пронумерованный набор элементов одного типа с общим именем: только
int, толькоdoubleили толькоchar; - массив объявляется так:
тип имя[размер];. Без инициализации в элементах лежит мусор, а пустые фигурные скобки{}заполняют массив нулями; - размер массива должен быть известен на этапе компиляции — это литерал или константа — и не может меняться во время работы программы. Если количество элементов вводит пользователь, объявляйте массив «с запасом»;
- индексы элементов идут от 0 до размера массива минус 1, а к элементу обращаются так:
data[i]; - узнать размер массива можно с помощью
std::size(data)илиsizeof(data) / sizeof(data[0]); - элементы массива вводят, выводят и обрабатывают в цикле
for (int i = 0; i < n; i++); - за выходом за границы массива компилятор не следит — следите Вы сами. Обращение к несуществующему элементу — это неопределённое поведение.
В следующем уроке мы перейдём к двумерным массивам — матрицам.
Теория без практики быстро забывается, поэтому обязательно закрепите материал. Авторизуйтесь на сайте, отметьте статью как прочитанную и перейдите во вкладку «Решать задачи». Отправляйте решения на проверку, разбирайте результаты тестов и отслеживайте свой прогресс.
Использованная литература
- Рабочий проект стандарта C++ [Электронный ресурс]. — URL: https://eel.is/c++draft/ (дата обращения: 20.10.2026).
- Рабочий проект стандарта C++26 — N5054 [Электронный ресурс]. — URL: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/n5054.pdf (дата обращения: 20.10.2026).
- ISO/IEC 14882:2024 — язык программирования C++ [Электронный ресурс]. — URL: https://www.iso.org/standard/83626.html (дата обращения: 20.10.2026).
- Объявление массивов [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/array (дата обращения: 20.10.2026).
- Агрегатная инициализация [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/aggregate_initialization (дата обращения: 20.10.2026).
- Оператор индексации [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/operator_member_access (дата обращения: 20.10.2026).
- Неопределённое поведение [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/ub (дата обращения: 20.10.2026).
- Массивы переменной длины в GCC [Электронный ресурс]. — URL: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html (дата обращения: 20.10.2026).
- Programming: Principles and Practice Using C++, 3-е издание [Электронный ресурс]. — URL: https://www.stroustrup.com/PPP3.html (дата обращения: 20.10.2026).
- A Tour of C++, 3-е издание [Электронный ресурс]. — URL: https://www.stroustrup.com/tour3.html (дата обращения: 20.10.2026).