Как работает sizeof(arr) / sizeof (arr[0])?
при поиске размера массива в цикле for я видел, как люди пишут
int arr[10];
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){}
Как sizeof(arr) / sizeof(arr[0])
длина массива? Как это технически работает?
6 ответов
если у вас array
затем sizeof(array)
возвращает количество байтов, которое занимает массив. Поскольку каждый элемент может занимать более 1 байта пространства, вы должны разделить результат на размер одного элемента (sizeof(array[0])
). Это дает вам количество элементов в массиве.
пример:
std::uint32_t array[10];
auto sizeOfInt = sizeof(std::uint32_t); // 4
auto numOfBytes = sizeof(array); // 10*sizeOfInt = 40
auto sizeOfElement = sizeof(array[0]); // sizeOfInt = 4
auto numOfElements = sizeof(array) / sizeof(array[0]); // numOfBytes / sizeOfElement = 40 / 4 = 10
обратите внимание, что если вы передаете массив в функцию, выше не сработает, так как массив распадается на указатель и sizeof(array)
возвращает размер указателя.
std::size_t function(std::uint32_t a[]) // same for void function(std::uint32_t a[10])
{
return sizeof(a); // sizeof(std::uint32_t*)!
}
std::uint32_t array[10];
auto sizeOfArray = function(array); // array decays to a pointer inside function()
как описано в стандарте C++ (5.3.3 Sizeof)
1 оператор sizeof возвращает количество байтов в объекте представление его операнда. Операнд является выражением, который является недооцененным операндом (пункт 5) или заключенным в скобки тип-идентификатор.
в этом выражении
sizeof(arr) / sizeof(arr[0])
используются два подвыражения с оператором sizeof.
этот подвыражение
sizeof(arr)
дает количество байтов, занятых массивом arr
(я полагаю, что arr
массив).
например, если вы объявили массив типа
int arr[10];
затем компилятор должен зарезервировать память, чтобы удерживать 10 элементов типа int. Если, например,sizeof( int )
равно 4, тогда компилятор зарезервирует 10 * 4 = 40 байт памяти.
подвыражения
sizeof(arr[0])
дает количество байтов занято одним элементом массива. Вы можете использовать любой индекс, например
sizeof(arr[1000])
потому что выражение не оценено. Важно только размер в байтах объекта (элемента массива) используется внутри оператора.
таким образом, если вы знаете общее количество байтов, зарезервированных для массива
sizeof(arr)
и знать, сколько байтов занимает каждый элемент массива (все элементы массива имеют одинаковый размер), то вы можете вычислить количество элементов в массиве с помощью формулы
sizeof(arr) / sizeof(arr[0])
вот простое соотношение. Если у вас есть массив из n элементов типа T
T arr[N];
а вы знаете размер памяти, занимаемой массивом, то вы можете рассчитать размер своего элемента, используя формулу
sizeof( arr ) / N == size of an element of the array.
и наоборот
если вы знаете размер памяти, занимаемой массивом и размер его элемента можно вычислить количество элементов в массив
sizeof( arr ) / sizeof( a[0] ) == N - number of elements in the array
последнее выражение можно переписать также следующим образом
sizeof( arr ) / sizeof( T ) == N - number of elements in the array
потому что элементы массива имеют тип T и каждый элемент массива занимает ровно то количество байтов, которое требуется для выделения объекта типа T.
примите во внимание, что обычно новички делают такую ошибку. Они передают массив в качестве аргумента функции. Например предположим, что у вас есть функция
void f( int a[] )
{
// ...
}
и передать в функцию массив
int arr[10];
f(arr);
затем функция использует указатель на первый элемент массива. На самом деле функция имеет объявление
void f( int *a )
{
// ...
}
Итак, если вы пишете, например, в функции
void f( int *a )
{
size_t n = sizeof( a ) / sizeof( a[0] );
// ...
}
тогда как a
внутри функции указатель (не массив), то вы получите что-то вроде
void f( int *a )
{
size_t n = sizeof( int * ) / sizeof( int );
// ...
}
обычно размер указателя равен 8 или 4 байта в зависимости от используемой среды. И вы не получите количество элементов. Вы получите какую-то странную ценность.
это работает только если arr
не распадается на указатель, то есть это тип массива, не тип указателя.
sizeof(arr)
- общий размер, занимаемый массивом.
sizeof(arr[0])
- размер первого элемента в массиве. (Обратите внимание, что массивы нулевой длины запрещены в C++, поэтому этот элемент всегда существует, если сам массив существует).
так как все элементы будут одинакового размера, количество элементов sizeof(arr) / sizeof(arr[0])
.
при работе с массивом (some_type name[some_size]
) sizeof(name)
- Это сколько байтов занимает массив. Деление общего размера массива на размер одного элемента (sizeof(name[0])
) дает вам, сколько элементов в массиве.
C++ способ использования экстента, который позволяет u получить ряд элементов в N-м измерении массива. см.http://en.cppreference.com/w/cpp/types/extent для деталей
int values[] = { 1 };
std::extent<decltype(values)>::value == 1
int
- равно 4 байтамsizeof(int)
это означает: 1 * 4 = 4
int arr[10]
- держит 10 int
sizeof(arr)
это означает: 10 * 4 = 40, мы получили 10 int
и все int
есть 4 байта,, arr
без []
это означает, что все arr
.
sizeof(arr[0])
это означает: 1 * 4 = 4
sizeof(arr) / sizeof(arr[0])
= 10*4 / 1*4 = 10,, и это длина массива.