2015-11-04 2 views
11

При поиске размера массива в цикле я видел, как люди пишутКак размер size (arr)/sizeof (arr [0]) работает?

for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++){} 

Как sizeof(arr)/sizeof(arr[0]) длина массива? Как это технически работает?

+0

Добавьте определение 'arr' к вопросу, иначе оно неоднозначно. – jepio

+0

@jepio Он говорит, что это массив, и код получает длину массива, поэтому можно считать, что 'arr' - это массив. – juanchopanza

ответ

18

Если у вас есть 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 

LIVE EXAMPLE

Обратите внимание, что если вы передать массив в функцию, выше не будет работать, так как массив распадается на указатель и 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() 

LIVE EXAMPLE #2

3

Он работает только тогда, когда arr не распадались в указатель, то есть, это тип массива, не тип указателя.

sizeof(arr) - общий размер, занимаемый массивом.

sizeof(arr[0]) - размер первого элемента в массиве. (Обратите внимание, что массивы нулевой длины не разрешены в C++, поэтому этот элемент всегда существует, если сам массив существует).

Поскольку все элементы будут иметь одинаковый размер, количество элементов равно sizeof(arr)/sizeof(arr[0]).

1

При работе с массивом (some_type name[some_size]) sizeof(name) - сколько байтов занимает массив. Разделение общего размера массива на размер одного элемента (sizeof(name[0])) дает вам количество элементов в массиве.

3

Как описано в стандарте 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 байтам в зависимости от используемой среды. И вы не получите количество элементов. Вы получите какую-то странную ценность.

Смежные вопросы