C/C++ Array Size
In C programming, arrays are used to store objects of the same type. Unlike the STL container std::vector in C++, determining the number of bytes for C arrays and the number of elements in C arrays are not straightforward.
In this blog post, I would like to discuss some of the concepts behind C arrays and how to determine the size of C arrays if it is possible.
Create Arrays
There are two types of arrays. The size of one type of the arrays would need to be known at compile-time, and the size of the other type of the arrays could be known at runtime. The former array would be created on the stack, and the latter array would be created on the heap.
To compile the program, please run the following command in the terminal.
C/C++ sizeof Operator
In C/C++, sizeof is used to determine the size of a variable or a type. Although the sizeof expressions, such as sizeof(variable) and sizeof(type) , could be used with parentheses, sizeof is a compile-time operator instead of a function in C/C++. This means that the compiler knows the exact value of sizeof(variable) and sizeof(type) at compile time.
Determine Array Size
The correct way of determining the size of arrays on the stack has been presented as follows. The size of arrays on the heap could not be determined.
To compile the program, please run the following command in the terminal.
I got the following outputs from the program. Some of the values might be different depending on the computers.
The questions is why sizeof(arr1) and sizeof(ptrArr1) result in different values. The compiler knows arr1 is neither a variable of integer nor a pointer of int, but an integer array of size 10. Therefore, sizeof(arr1) is returning the number of bytes for the array arr1 . It is some of the few cases where the array type does not decay to a pointer type. ptrArr1 , however, is just a normal pointer decayed from integer array type. Therefore, sizeof(ptrArr1) is returning the number of bytes for a single pointer ptrArr1 .
What are the differences between malloc and new?
Obviously, one major difference is that malloc does not call constructor since it does not have to know the type of variables we want to write to the memory, while new has to call a constructor.
How does delete and free know the size of an array?
It is a little bit weird that we could not determine the size of an array on the heap, but free and delete[] knows the number of bytes for the array so that they could recycle the memory accordingly. The answer is it really depends on the implementation.
There is a good diagram on the StackOverflow which I borrowed. It is a good implementation for the arrays on the heap.
free and delete[] could always look at the headers on the memory before the pointer and determine the size of the array, because free and delete[] assume all the pointers given to them are pointers pointing to the memories on the heap. sizeof , however, has no such assumptions. In addition, as mentioned above sizeof is a compile-time operator and it could not look at the potential header at runtime.
Что такое array size
Array classes are generally more efficient, light-weight and reliable than C-style arrays. The introduction of array class from C++11 has offered a better alternative for C-style arrays.
size() function is used to return the size of the list container or the number of elements in the list container.
Syntax :
Errors and Exceptions
1. It has a no exception throw guarantee.
2. Shows error when a parameter is passed.
ArraySize
Для одномерного массива значение, возвращаемое функцией ArraySize , равно значению ArrayRange(array,0).
void OnStart ()
<
//— создание массивов
double one_dim[];
double four_dim[][10][5][2];
//— размеры
int one_dim_size=25;
int reserve=20;
int four_dim_size=5;
//— вспомогательная переменная
int size;
//— выделим память без резервирования
ArrayResize (one_dim,one_dim_size);
ArrayResize (four_dim,four_dim_size);
//— 1. одномерный массив
Print ( "+==========================================================+" );
Print ( "Размеры массивов:" );
Print ( "1. Одномерный массив" );
size= ArraySize (one_dim);
PrintFormat ( "Размер нулевого измерения = %d, Размер массива = %d" ,one_dim_size,size);
//— 2. многомерный массив
Print ( "2. Многомерный массив" );
size= ArraySize (four_dim);
PrintFormat ( "Размер нулевого измерения = %d, Размер массива = %d" ,four_dim_size,size);
//— размеры измерений
int d_1= ArrayRange (four_dim,1);
int d_2= ArrayRange (four_dim,2);
int d_3= ArrayRange (four_dim,3);
Print ( "Проверка:" );
Print ( "Нулевое измерение = Размер массива / (Первое измерение * Второе измерение * Третье измерение)" );
PrintFormat ( "%d = %d / (%d * %d * %d)" ,size/(d_1*d_2*d_3),size,d_1,d_2,d_3);
//— 3. одномерный массив с резервированием памяти
Print ( "3. Одномерный массив с резервированием памяти" );
//— увеличим значение в 2 раза
one_dim_size*=2;
//— выделим память с резервированием
ArrayResize (one_dim,one_dim_size,reserve);
//— распечатаем размер
size= ArraySize (one_dim);
PrintFormat ( "Размер с резервированием = %d, Реальный размер массива = %d" ,one_dim_size+reserve,size);
>
Как определить длину массива в C++
По сути, когда мы говорим о длине массива, мы имеем в виду общее количество элементов, присутствующих в соответствующем массиве. Например, посмотрите на массив ниже:
Размер (или длина) массива равна общему количеству элементов в нем. Следовательно, в данном случае это «5».
Способы определения длины массива в C++
Теперь давайте посмотрим на различные способы, с помощью которых мы можем выяснить длину массива в C++:
- поэлементный подсчет,
- begin() и end(),
- функция sizeof(),
- функция size() в STL,
- указатели.
Теперь давайте обсудим каждый метод подробно и с примерами.
1: Поэлементный подсчет
Самый очевидный способ – перебрать заданный массив и одновременно подсчитать общее количество перебранных элементов.
Но если мы заранее не знаем длину массива для итерации, то в таком случае мы не можем использовать цикл for. Эту проблему можно решить, используя простой цикл for-each. Внимательно посмотрите на приведенный ниже код.
Вы получите такой результат:
Как мы говорили выше, здесь мы перебираем весь массив arr, используя цикл for-each с итератором i. Значение счетчика c увеличивается по мере итерации. Когда перебор закончится, в c вы найдете длину данного массива.
2: Функции begin() и end()
Мы также можем вычислить длину массива, используя стандартные функции begin() и end(). Эти две функции возвращают итераторы, указывающие на начало и конец массива соответственно. Внимательно посмотрите на данный код:
Следовательно, разница между возвращаемыми значениями двух функций end() и begin() дает нам размер или длину данного массива. Данный код вернет:
3: Функция sizeof()
Оператор sizeof() в C++ возвращает размер переданной переменной или данных в байтах. Кроме того, он возвращает общее количество байтов, необходимых для хранения массива. Следовательно, если мы просто разделим размер массива на размер, занимаемый каждым его элементом, мы узнаем общее количество элементов, присутствующих в массиве.
Давайте посмотрим, как это работает:
В результате мы получим:
4: Функция size() в STL
В стандартной библиотеке есть функция size(), которая возвращает количество элементов в заданном контейнере (в нашем случае это массив).
В результате вы получите:
5: Определение длины массива с помощью указателей
Узнать длину массива можно с помощью указателей. Давайте посмотрим, как это делается:
В результате мы получим:
Выражение *(arr+1) выдает адрес области памяти сразу после последнего элемента массива. Следовательно, разница между ним и начальным местоположением массива (или базовым адресом, arr) показывает общее количество элементов, присутствующих в данном массиве.
Заключение
Итак, в этом мануале мы обсудили различные методы определения длины массива в C++. Все приведенные выше методы просты в использовании, однако мы предпочитаем применять цикл for-each – не только из-за удобочитаемости кода, но и из-за его кросс-платформенной надежности.