Как найти длину массива в C++? Проблема с sizeof и указателями
Почему ваш код не работает?
Проблема в том, что в C++ массивы при передаче в функцию распадаются (decay) в указатели. Когда вы пишете:
void printArrayLength(int arr[])
Компилятор на самом деле видит это как:
void printArrayLength(int* arr)
То есть arr — это уже не массив, а указатель на первый элемент. sizeof(arr) возвращает размер указателя (обычно 4 или 8 байт в зависимости от архитектуры), а не размер всего массива. Поэтому sizeof(arr) / sizeof(arr[0]) даёт 1 или 2, но не 5.
Надёжные способы узнать длину массива
Вот несколько проверенных подходов:
- Передавать размер отдельным параметром — классический C-стиль
- Использовать шаблоны — современный C++
- Использовать std::array или std::vector — рекомендуемый подход
Способ 1: Передавать размер отдельно
void printArrayLength(int arr[], int size) {
cout << "Длина массива: " << size;
}
int main() {
int myArray[] = {10, 20, 30, 40, 50};
int size = sizeof(myArray) / sizeof(myArray[0]);
printArrayLength(myArray, size);
return 0;
}
Это простой, но подверженный ошибкам способ — легко забыть передать правильный размер.
Способ 2: Шаблонная функция (C++11 и новее)
template <size_t N>
void printArrayLength(int (&arr)[N]) {
cout << "Длина массива: " << N;
}
int main() {
int myArray[] = {10, 20, 30, 40, 50};
printArrayLength(myArray); // Выведет 5
return 0;
}
Здесь мы передаём массив по ссылке, сохраняя его размер. Компилятор сам выводит N. Недостаток: функция работает только с массивами фиксированного размера, а не с указателями.
Способ 3: Использовать std::size (C++17)
#include <iostream>
#include <array>
int main() {
int myArray[] = {10, 20, 30, 40, 50};
cout << "Длина массива: " << std::size(myArray); // Выведет 5
return 0;
}
std::size — это безопасная обёртка, которая работает и с обычными массивами, и с контейнерами STL.
Способ 4: Использовать std::array (рекомендуется)
#include <iostream>
#include <array>
void printArrayLength(const std::array<int, 5>& arr) {
cout << "Длина массива: " << arr.size(); // Выведет 5
}
int main() {
std::array<int, 5> myArray = {10, 20, 30, 40, 50};
printArrayLength(myArray);
return 0;
}
std::array не теряет информацию о размере и предоставляет удобный метод .size(). Для динамических массивов используйте std::vector.
Итог
Запомните главное правило: в C++ массивы и указатели — не одно и то же, хотя они тесно связаны. Никогда не используйте sizeof на массиве, переданном в функцию. Вместо этого:
- Для статических массивов — используйте
std::sizeили шаблоны - Для современного кода — используйте
std::arrayилиstd::vector - Для обратной совместимости — передавайте размер отдельно
Альтернативный подход: макросы (C-style, с осторожностью)
В старом коде иногда встречается макрос для определения размера массива:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
int myArray[] = {1, 2, 3, 4, 5};
int size = ARRAY_SIZE(myArray); // Работает, пока arr — массив, а не указатель
Этот макрос опасен тем, что он не выдаст ошибку, если передать указатель — просто вернёт неверный результат. В современном C++ лучше использовать std::size или шаблоны.
Для динамических массивов
Если вы работаете с динамической памятью (new[]), то размер хранить нужно вручную. Никакой sizeof тут не поможет:
int* arr = new int[10];
// Размер (10) нужно запомнить отдельно
delete[] arr;
Поэтому для динамических массивов всегда используйте std::vector — он сам хранит размер и безопасно управляет памятью:
std::vector<int> vec = {1, 2, 3, 4, 5};
cout << vec.size(); // Выведет 5
Это избавит вас от головной боли с sizeof и утечками памяти.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги