c++ arrays pointer-arithmetic

c++ - ¿Puedes explicar el propósito de array+5 en este programa?



arrays pointer-arithmetic (5)

La array variable es como un puntero al comienzo de la memoria que contiene los datos.

La longitud de la array es 5 , por lo que agregar 5 al principio da la posición de uno más allá del final.

start --| 10, 20, 29, 200, 2, (out of array) |--- +5 -----------^

La condición it != end comprueba si el bucle no está fuera de los límites.

Entiendo cómo funciona la mayor parte, a excepción de la segunda línea en la función main : int* end = array+5; . ¿Cómo funciona esa línea?

#inlcude <iostream> int main() { int array[] = {10, 20, 29, 200, 2}; int* end = array+5; for(int* it = array; it != end; ++it) { std::cout << *it << std::endl; } }

Se supone que solo imprime todos los elementos de la lista.


Para cualquier matriz o puntero a e índice i , la expresión a[i] es exactamente igual a *(a + i) . Junto con la disminución de la matriz (lo que significa que, por ejemplo, la array es igual a &array[0] ) significa que la array + 5 será igual a &array[5] .

Por lo tanto, su ciclo está iterando desde &array[0] (que es lo que es igual a la array ) a one &array[4] (inclusive). El ciclo está iterando sobre los cinco elementos de la array , haciendo it apunte a cada elemento o la matriz a su vez.


Para entender int* end = array+5; , uno debe saber cómo se ha establecido la memoria para int array[] = {10, 20, 29, 200, 2} . Han representado lo mismo a continuación para una mejor comprensión. Las direcciones se dan en decimales y hexadecimales para realizar operaciones aritméticas fácilmente.

Address table ----------------------------------------------------------- array ===>| 100 | 104 | 108 | 112 | 116 | 120 | -----> DECIMAL | 0x100 | 0x104 | 0x108 | 0x10C | 0x110 | 0x114 | -----> HEXADECIMAL ----------------------------------------------------------- | | | | | 10 20 29 200 2 ''array'' will be pointing to 0x100

La declaración int* end = array + 5; se compila en un código que es equivalente a int* end = (array + (sizeof(int) * 5));

Por lo tanto, se evalúa como int* end = (0x100 + (4 * 5)) = 0x114(decimal equivalent 120); cual es la dirección al lado del último elemento. Así que end estará apuntando al penúltimo elemento.

Es importante recordar que el valor que se debe agregar o restar de la dirección base de la matriz siempre depende del tipo de datos que es int en su caso y se supone que el sizeof(int) es de 4 bytes .

En una nota al margen, datatype arr [index]; se evalúa como *(arr + (sizeof(datatype) * index)) .


array + 5 es equivalente a &array[5] .

Dado que la array en su código de muestra es una matriz de cinco elementos.

int array[] = {10, 20, 29, 200, 2};

la inicialización

int* end = array+5;

hace que end sea ​​un puntero a uno pasado el final de la matriz, y la condición final en el bucle

for(int* it = array; it != end; ++it) { std::cout << *it << std::endl; }

significa que el bucle termina una vez it apunta más allá del final de la matriz (en su ejemplo, apunta a la array[5] ). Esto está perfectamente bien en C ++, ya que se permite calcular o comparar un puntero a uno más allá del final de una matriz con otros punteros a elementos de esa matriz. Sin embargo, al desreferenciar dicho puntero (por ejemplo, en su ejemplo, usarlo para acceder al valor de array[5] ) provoca un comportamiento indefinido.

En C ++ 11 y posterior, las funciones std::begin() y std::end() (del encabezado estándar <iterator> ) si se les da un argumento de matriz, devuelven las direcciones del primer elemento y one-past-the -último elemento respectivamente. Entonces, su código es funcionalmente equivalente, para una array tiene cinco elementos, a;

int *end = std::end(array); for(int *it = std::begin(array); it != end; ++it) { std::cout << *it << std::endl; }

También es equivalente al más conciso, y a menudo se prefiere ya que es menos propenso a errores;

for (const auto &element : array) // const since the loop body doesn''t change the array { std::cout << element << std::endl; }


it != end;

significa que alcanzó la posición [5], que es una después de la última (4).

int* end = array + 5;

simplemente crea una variable que apunta a esa [5] posición.

Funciona, pero una versión mucho más limpia y segura es:

for(int i = 0 ; i < 5 ; i++) { std::cout << it[i] << std::endl; }

Por supuesto, puede reemplazar el 5 codificado con sizeof(array)/sizeof(int) , o, mejor aún, usar un std :: array.

std::array arr<int,5> = {10, 20, 29, 200, 2}; for(int i = 0 ; i < arr.size() ; i++) { std::cout << arr[i] << std::endl; }

o

std::array arr<int,5> = {10, 20, 29, 200, 2}; for(auto& it : arr) { std::cout << it << std::endl; }

Las últimas formas son tan rápidas como la matriz sin formato simple, pero mucho más seguras.