c++ - ¿Cómo funcionan sizeof(arr)/sizeof(arr[0])?
(6)
Como se describe en el Estándar C ++ (5.3.3 Sizeof)
1 El operador sizeof produce el número de bytes en la representación del objeto de su operando. El operando es una expresión, que es un operando no evaluado (Cláusula 5), o una identificación de tipo entre paréntesis.
En esta expresion
sizeof(arr) / sizeof(arr[0])
Se utilizan dos subexpresiones con el operador sizeof.
Esta subexpresión
sizeof(arr)
produce el número de bytes ocupados por la matriz
arr
(supongo que
arr
es una matriz).
Por ejemplo, si declaró una matriz como
int arr[10];
entonces el compilador tiene que reservar memoria para contener 10 elementos de tipo int.
Si, por ejemplo,
sizeof( int )
es igual a 4, el compilador reservará 10 * 4 = 40 bytes de memoria.
Subexpresión
sizeof(arr[0])
da el número de bytes ocupados por un elemento en la matriz. Puedes usar cualquier índice como por ejemplo
sizeof(arr[1000])
porque la expresión no está evaluada. Solo es importante el tamaño en bytes del objeto (un elemento de la matriz) utilizado dentro del operador.
Por lo tanto, si conoce el total de bytes que estaban reservados para una matriz
sizeof(arr)
y saber cuántos bytes ocupa cada elemento de la matriz (todos los elementos de una matriz tienen el mismo tamaño), entonces puede calcular la cantidad de elementos en la matriz utilizando la fórmula
sizeof(arr) / sizeof(arr[0])
Aquí hay una relación simple. Si tiene una matriz de N elementos de tipo T
T arr[N];
y sabes el tamaño de la memoria ocupada por la matriz, entonces puedes calcular el tamaño de su elemento usando la fórmula
sizeof( arr ) / N == size of an element of the array.
Y viceversa
Si conoce el tamaño de la memoria ocupada por la matriz y el tamaño de su elemento, puede calcular la cantidad de elementos en la matriz
sizeof( arr ) / sizeof( a[0] ) == N - number of elements in the array
La última expresión puede reescribir también de la siguiente manera
sizeof( arr ) / sizeof( T ) == N - number of elements in the array
porque los elementos de la matriz tienen tipo T y cada elemento de la matriz ocupa exactamente la cantidad de bytes necesarios para asignar un objeto de tipo T.
Tenga en cuenta que generalmente los principiantes cometen tal error. Pasan una matriz como argumento a una función. Por ejemplo, supongamos que tiene una función
void f( int a[] )
{
// ...
}
Y pasas a la función tu matriz
int arr[10];
f(arr);
entonces la función usa el puntero al primer elemento de la matriz. De hecho, la función tiene declaración
void f( int *a )
{
// ...
}
Entonces, si escribes, por ejemplo, dentro de la función
void f( int *a )
{
size_t n = sizeof( a ) / sizeof( a[0] );
// ...
}
entonces como dentro de la función es un puntero (no es una matriz), entonces obtendrá algo como
void f( int *a )
{
size_t n = sizeof( int * ) / sizeof( int );
// ...
}
Por lo general, el tamaño de un puntero es igual a 8 o 4 bytes, según el entorno utilizado. Y no obtendrás el número de elementos. Obtendrás un valor extraño.
Al buscar un tamaño de una matriz en un bucle for, he visto a personas escribir
int arr[10];
for(int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){}
¿Cómo es
sizeof(arr) / sizeof(arr[0])
la longitud de la matriz?
¿Cómo funciona técnicamente?
Cuando se trata de una matriz (
some_type name[some_size]
)
sizeof(name)
es cuántos bytes ocupa la matriz.
Dividir el tamaño total de la matriz por el tamaño de un elemento (
sizeof(name[0])
) le da cuántos elementos hay en la matriz.
Si tiene una
array
,
sizeof(array)
devuelve el número de bytes que ocupa la matriz.
Como cada elemento puede ocupar más de 1 byte de espacio, debe dividir el resultado con el tamaño de un elemento (
sizeof(array[0])
).
Esto le da un número de elementos en la matriz.
Ejemplo:
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
Tenga en cuenta que si pasa una matriz a una función, lo anterior no funcionará ya que la matriz se descompone en un puntero y
sizeof(array)
devuelve el tamaño del puntero.
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()
Solo funciona si
arr
no se ha descompuesto en un puntero, es decir, es un tipo de matriz,
no
un tipo de puntero.
sizeof(arr)
es el tamaño total ocupado por la matriz.
sizeof(arr[0])
es el tamaño del primer elemento en la matriz.
(Tenga en cuenta que las matrices de longitud cero no están permitidas en C ++, por lo que este elemento siempre existe si la matriz en sí existe).
Dado que todos los elementos serán del mismo tamaño, el número de elementos es
sizeof(arr) / sizeof(arr[0])
.
c ++ forma de usar la extensión, que le permite obtener una serie de elementos en la enésima dimensión de la matriz. ver http://en.cppreference.com/w/cpp/types/extent para más detalles
int values[] = { 1 };
std::extent<decltype(values)>::value == 1
int
- es igual a 4 bytes
sizeof(int)
significa: 1 * 4 = 4
int arr[10]
- tiene 10
int
sizeof(arr)
significa: 10 * 4 = 40, tenemos 10
int
y cada
int
tiene 4 bytes ,,
arr
sin el
[]
significa todo el
arr
.
sizeof(arr[0])
significa: 1 * 4 = 4
sizeof(arr) / sizeof(arr[0])
= 10 * 4/1 * 4 = 10 ,, y es la longitud de la matriz.