C-массивы и std::array
Пять оценок можно хранить в пяти переменных, но сложить их в цикле не получится: у каждой своё имя. Массив (array) хранит несколько значений одного типа под одним именем, а к каждому значению обращаются по номеру:
#include <iostream>
int main() {
int scores[5] = {90, 75, 60, 85, 70};
int sum = 0;
for (int s : scores) {
sum = sum + s;
}
std::cout << scores[0] << ' ' << scores[4] << '\n'; // 90 70
std::cout << sum << '\n'; // 380
}Запись int scores[5] объявляет массив из пяти int, которые лежат в памяти подряд. Элементы нумеруются с нуля, поэтому последний — scores[4]. Цикл по диапазону проходит по всем пяти элементам.
Размер — часть типа
Число в квадратных скобках входит в тип: scores имеет тип int[5], а int[3] — уже другой тип. Поэтому размер должен быть известен при компиляции — например, литерал или constexpr-переменная. sizeof(scores) даёт размер всего массива в байтах, а деление на размер одного элемента — число элементов:
int scores[5] = {90, 75, 60, 85, 70};
std::cout << sizeof(scores) / sizeof(scores[0]) << '\n'; // 5Свои границы C-массив не проверяет. Обращение по номеру за его пределами, например scores[5], — неопределённое поведение.
Массив в параметре
Скопировать C-массив в параметр функции нельзя. Вместо этого функция получает указатель (pointer) на первый элемент — это называют преобразованием массива в указатель (array-to-pointer decay). Параметр int a[5] означает то же, что int* a, а число в скобках компилятор игнорирует.
Поэтому sizeof(a) внутри функции даёт размер указателя, а не массива, и длину по нему не узнать. Её передают в функцию отдельным параметром, как n в задачах на указатели.
std::array
Массив типа std::array<int, 5> из заголовка <array> хранит те же пять int подряд, но копируется и передаётся в функцию целиком, как int. В указатель он не превращается, а size() возвращает число элементов. Передают его по const-ссылке, как и другие объекты, которые дорого копировать.
#include <array>
#include <iostream>
int total(const std::array<int, 5>& values) {
int sum = 0;
for (int v : values) {
sum = sum + v;
}
return sum;
}
int main() {
std::array<int, 5> scores = {90, 75, 60, 85, 70};
std::cout << scores.size() << ' ' << total(scores) << '\n'; // 5 380
}В угловых скобках стоят тип элементов и их число. Размер и здесь входит в тип, поэтому total принимает только массив ровно из пяти int.
Частая ошибка
Число элементов считают внутри функции:
int count(int a[5]) {
return sizeof(a) / sizeof(a[0]); // ✗
}warning: sizeof on array function parameter will return size of 'int *' instead of 'int[5]' [-Wsizeof-array-argument]Это предупреждение, а не ошибка: функция компилируется, но a в ней — указатель. sizeof(a) даёт размер указателя, и результат не зависит от длины массива. Передайте длину вторым параметром или возьмите std::array.