При поиске размера массива в цикле я видел, как люди пишутКак размер size (arr)/sizeof (arr [0]) работает?
for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++){}
Как sizeof(arr)/sizeof(arr[0])
длина массива? Как это технически работает?
При поиске размера массива в цикле я видел, как люди пишутКак размер size (arr)/sizeof (arr [0]) работает?
for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++){}
Как sizeof(arr)/sizeof(arr[0])
длина массива? Как это технически работает?
Если у вас есть 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()
Он работает только тогда, когда arr
не распадались в указатель, то есть, это тип массива, не тип указателя.
sizeof(arr)
- общий размер, занимаемый массивом.
sizeof(arr[0])
- размер первого элемента в массиве. (Обратите внимание, что массивы нулевой длины не разрешены в C++, поэтому этот элемент всегда существует, если сам массив существует).
Поскольку все элементы будут иметь одинаковый размер, количество элементов равно sizeof(arr)/sizeof(arr[0])
.
При работе с массивом (some_type name[some_size]
) sizeof(name)
- сколько байтов занимает массив. Разделение общего размера массива на размер одного элемента (sizeof(name[0])
) дает вам количество элементов в массиве.
Как описано в стандарте C++ (5.3.3) SIZEOF
1 Оператор SizeOf дает число байтов в представлении объекта его операнда. Операндом является либо выражение, , которое является неоцененным операндом (п. 5), либо идентификатором типа в скобках.
В этом выражении
sizeof(arr)/sizeof(arr[0])
используют два подвыражения с оператором SIZEOF.
Это Подвыражение
sizeof(arr)
дает число байтов, занимаемых массивом arr
(я полагаю, что arr
массив).
Например, если вы объявили массив, как
int arr[10];
, то компилятор должен зарезервировать память, чтобы держать 10 элементов типа междунар. Если, например, 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' к вопросу, иначе оно неоднозначно. – jepio
@jepio Он говорит, что это массив, и код получает длину массива, поэтому можно считать, что 'arr' - это массив. – juanchopanza