Hola y bienvenido de nuevo. En esta conferencia quiero hablar sobre aritmética de puntos.
Ahora que entendemos la relación entre matrices y punteros,
este concepto será más fácil de entender.
Decimos aritmética, pero en realidad no lo hacemos,
todo lo que realmente significa es que
puede hacer más o menos o incrementar o disminuir en un puntero.
Entonces, el poder real de usar punteros a matrices entra en juego cuando desea secuenciar a
través de los elementos de una matriz.
Desea ir desde el primer elemento hasta el final, desea recorrerlos en iteración.
Estos son los verdaderos indicadores de poder. Debido a que los punteros apuntan
a direcciones de uso, cada elemento de la matriz es simplemente otra dirección.
Por lo tanto, puede hacer más más en los punteros y puede ir a la siguiente dirección.
Entonces, aquí el puntero de valores se puede usar para acceder al primer número entero
de la matriz de valores.
Se puede utilizar para acceder a valores por debajo de 0.
Entonces, si recuerda valores, el puntero es un puntero que apunta
a una matriz de enteros.
Y lo asignamos al primer elemento de la matriz simplemente asignando el puntero al nombre de la matriz.
También podríamos usar la dirección del operador sub-0 si quisiéramos.
Pero cuando desreferenciamos el puntero de valores porque
apunta al primer elemento de la matriz, le dará
el primer número entero en la matriz de valores por debajo de 0.
Si desea hacer referencia al valor sub 3 a
través de la variable de puntero, todo lo que tiene que hacer es agregar 3 al puntero de valores
y luego aplicar el operador de indirección para eliminar la referencia.
Así que podrías hacer algo como esto. Puede decir el puntero de valores más 3
y luego desreferenciarlo con el asterisco.
Y por lo general, coloca el asterisco fuera de las comillas para que quede claro.
Pero lo que está haciendo es decir puntero de
valores, que es una dirección del primer elemento en la matriz, le está agregando 3.
Y entonces en realidad sumará por cada bytes para los enteros, va
a multiplicar los bytes por los enteros.
Pero esto esencialmente apuntará al sub 3, el
cuarto elemento de la matriz.
Entonces, en la expresión asterisco valora el puntero más i que
se puede usar para acceder a cualquier valor contenido en una matriz de valores.
Entonces, si comprende esta expresión, puede agregar cualquier cosa a i y
le señalará una matriz de elementos específica.
Entonces, si desea establecer un valor por debajo de 10 a 27, todo
lo que tiene que hacer es si está usando un
puntero es decir el puntero de valores más 10 y luego desreferenciarlo y decir igual a 27.
Entonces ves la sintaxis diferente aquí.
Nuevamente, es una conveniencia de notación, pero también es más eficiente en términos del programa en sí.
Entonces, los punteros debido a que están tan estrechamente relacionados con
las matrices, puede acceder fácilmente a los elementos simplemente incrementando los punteros
decrecientes o agregando valores o restando valores de un puntero.
Muy, muy útil.
Para configurar el puntero de valores para que apunte al segundo elemento de la matriz
de valores, puede aplicar el operador de dirección al valor sub 1 y asignar los resultados al puntero de valores.
Vimos esto. Esta es solo otra forma de hacer lo mismo
que mencioné anteriormente si desea utilizar el suboperador de direcciones.
Siempre puede hacer esto si lo
desea, pero es mucho más conveniente hacer aritmética de punteros.
Si el puntero de valores apunta a un valor por
debajo de 0, puede establecer en el punto de valores de uno simplemente agregando uno
al valor de puntero de valores. Y esto es realmente a lo que estamos llegando con la aritmética de puntos.
Todo lo que tiene que hacer es decir que los valores apuntan
o más es igual a uno, y ahora el puntero de valores apunta al segundo elemento de la
matriz o al primer índice.
Muy, muy buena notación, muy fácil de hacer.
Entonces, esta es una expresión perfectamente válida en cy se
puede usar para punteros a cualquier tipo de datos, ya sea un
carácter entero o cualquier cosa. Y probablemente deberías pensar en lo útil que puede ser esto en los personajes.
Si tiene un puntero de carácter, ahora puede acceder a cada
elemento, a cada carácter de una cadena, simplemente haciendo un signo más en un puntero.
Los operadores de incremento y decremento más más y menos
menos son particularmente útiles cuando se trata de
estos punteros porque normalmente querrá pasar de un elemento al siguiente y así sucesivamente.
No es tan común sumar 22 o menos 20
porque normalmente se va en secuencia.
Entonces, usar el operador de incremento en un puntero tiene el mismo efecto que agregar uno al puntero.
Usar el operador de decremento tiene el mismo efecto que restar uno al puntero.
Por lo tanto, decir el puntero de valores más
más establecerá el puntero de valores que apunta al siguiente entero en la matriz de valores.
Menos menos debería ser el puntero de valores Va a
establecer el puntero de valores apuntando al entero anterior en la matriz de valores.
Pero debes tener cuidado cuando haces el menos menos
porque quieres asegurarte de que estás al menos en la matriz y no en 0.
Y lo mismo ocurre con plus plus.
Si está al final de la matriz, no querrá tener ningún error fuera de los límites.
Así que asegúrese de que el puntero de valores si
lo está disminuyendo, no apuntaba al principio de la matriz de valores inicialmente.
Otro ejemplo aquí donde
realmente vamos a sumar todos los elementos en una
matriz, verá que tenemos una función de suma
de matriz y la función toma
una matriz y también toma un entero constante como parámetros.
Dentro de la función, vamos a crear un número entero.
Vamos a inicializar esa suma entera a 0, y vamos a crear un puntero entero,
un puntero a de tipo int.
También crearemos un puntero que
sea constante.
Entonces, lo que eso significa es que no puede cambiar la dirección.
Siempre va a ser matriz más ny se llamará fin de matriz.
Estamos haciendo esto porque hace que nuestro bucle sea más eficiente si lo configuramos
para ir al final de la matriz y solo miramos el puntero.
Entonces, el final de la matriz apunta a la dirección del final de la matriz.
Podemos decir matriz, que es lo que se pasa y luego n es el
tamaño, el
tamaño de la matriz.
Ahora, el bucle for inicializará el puntero de la variable de control de bucle,
que es un puntero a la matriz. Y todo lo que tiene que hacer
es que si desea asignar un puntero al primer elemento de una matriz, todo lo que tiene que hacer es
decir que el puntero es igual a la matriz.
Y luego nuestra condición de salida del ciclo es si el puntero es menor que el final de la matriz.
Recuerde, un puntero es una dirección y el final de la matriz también es una dirección.
Entonces, estamos diciendo que si la dirección en el puntero es menor que el puntero
n, entonces queremos ejecutar el cuerpo del bucle.
El puntero es solo un número entero, es una dirección hexadecimal.
Cada vez que incrementamos, pasa a la siguiente dirección. Tenemos la dirección final, por lo que
podemos decir pasar por el bucle hasta que lleguemos al final.
Y luego estamos incrementando el puntero en sí, que va
a incrementar la dirección para ir al siguiente elemento de la matriz esencialmente porque
eso es lo que estamos apuntando.
Luego tenemos dentro del cuerpo de nuestro bucle, decimos suma más igual al puntero.
Estamos desreferenciando el puntero para obtener el valor
porque recuerde que queremos obtener el valor que no queremos que obtenga la dirección
del puntero o la dirección a la que apunta el puntero.
Y luego, al final, devolvemos la suma. Entonces esto va a sumar
todos los elementos en una matriz.
Notarás que en la página principal, también hicimos una declaración de la función allí
en lugar de la parte superior del archivo. Por lo general, me gusta ponerlos en la parte superior del archivo.
Pero en general, creamos una matriz de 10 elementos, 3 7 menos 9 y así sucesivamente.
Luego pasamos la matriz o una suma, y especificamos
el tamaño como 10.
Y lo que notará es que devuelve el valor que es la suma de la matriz.
Entonces, es muy, muy bueno usar esta aritmética de puntos para iterar a través de
una matriz, podemos simplemente
agregar a la siguiente dirección y también mirar la dirección final para saltar.
Esto es más eficiente si el puntero mira la dirección final en
lugar de un contador que mira menos de n.
Y también notará que las creamos como constantes porque las constantes no cambian y
eso es más eficiente con el compilador.
La matriz aquí es un puntero constante, lo que significa que la dirección no puede cambiar.
También debería haber notado en este
ejemplo que para pasar una matriz a una función, simplemente especifique el nombre de la matriz.
Entonces sabemos cómo pasar a subir la función. Y para producir un puntero a una matriz,
solo necesita especificar el nombre de la matriz.
Vimos eso cuando asignamos el primer elemento de la matriz a un puntero.
Entonces, lo que esto implica es que la llamada a su función de
suma de matriz que se pasó a la función fue en realidad un puntero a los valores de la matriz.
Y esto realmente le dice que las matrices y los punteros están muy, muy estrechamente relacionados, que
una matriz no es más que un puntero.
Y esto explica por qué puede cambiar los elementos de una matriz desde dentro de una función.
Porque hasta este punto, cuando pasa datos a una función, esos datos no se
cambian fuera de esa función a menos que sea un puntero.
Porque es por eso que tenemos que pasar la dirección del scanf.
La única forma en que los elementos se cambian fuera de una función
es si está pasando punteros a una función.
Y debido a que los elementos se modifican dentro de esa función,
esto implica que está pasando un puntero.
Y esto está demostrando nuevamente que cuando
las matrices y los punteros son muy, muy similares, las matrices son de hecho punteros que
usan una sintaxis diferente.
Vamos a hablar sobre cómo podemos pasar por referencia o realmente pasar
una copia de una referencia, lo que
le permitirá cambiar datos en una función fuera de esa función.
Si recuerda uno de nuestros desafíos anteriores,
cada vez que queríamos cambiar datos en una función, teníamos que
usar una variable global.
Porque no entendimos el concepto de
pasar por referencia y no entendimos el concepto de punteros.
Pero también mencioné anteriormente que una de las ventajas de los punteros
es que ahora puede cambiar los datos dentro de una función y se reflejarán fuera de esa función.
Pero esa es otra conferencia.
Pero ese concepto en sí mismo debido al ejemplo anterior está demostrando
cómo las matrices son esencialmente punteros.
Entonces, podría preguntarse por qué el parámetro formal dentro de la función no se declara como un puntero.
Bueno, podría ser. Podríamos hacer algo como esto, int array sum, int star array.
No necesitamos declarar eso como una matriz.
Es perfectamente válido porque las matrices y los punteros son los mismos que podemos decir int star array.
Mencionamos que están muy relacionados.
Por lo tanto, puede declarar un tipo de matriz como un tipo de matriz de
entradas dentro de la función de suma de matriz o puede declararlo como un puntero a int.
Y es por eso que ves muchas funciones que aceptan matrices como parámetros o
como argumentos donde los parámetros son en realidad punteros.
Entonces, si va a utilizar números de índice para hacer referencia a los elementos de una matriz que se
pasa a una función, declare el parámetro como una matriz.
Nuevamente, la conveniencia de la notación, es solo una forma diferente
de notación, ya sea usando los corchetes y el subíndice o usando un puntero.
La matriz en sí misma suele ser más fácil de
leer en términos de mantenimiento del programa; refleja más correctamente el uso de la matriz por parte de la función.
Pero el puntero es más fácil de usar.
Y si está utilizando un argumento como puntero a la matriz, declare que es de tipo
puntero en el parámetro formal.
Así que aquí hay un ejemplo con la notación de puntero de la
función donde el ejemplo anterior usaba una notación de matriz.
Aquí solo decimos int start array y
lo que notará es que la función inmediatamente se vuelve mucho
más pequeña, porque no tenemos que asignar el puntero a la matriz al primer
elemento como lo hicimos.
El ciclo también se vuelve mucho más pequeño porque no
necesitamos hacer esa asignación en la primera declaración.
Podemos simplemente decir hasta que la matriz sea menor que el final de la matriz
y podemos incrementar la matriz. Así que es un poco menos de
código, todavía está muy claro lo que está sucediendo, con suerte, si comprende las matrices y los punteros.
Estamos pasando una matriz int star, y
ya no tenemos que inicializar esa matriz porque la estamos pasando
en el puntero, ya no inicializamos el puntero.
Y luego, en realidad, estamos configurando la dirección del final de la
matriz en un puntero constante,
fin de matriz. Usamos eso para saltar
fuera del ciclo, y simplemente decimos suma más igual a
matriz de estrellas, usando el operador de indirección para desreferenciar la matriz nuevamente, devolviendo la suma.
Y luego, la función principal es exactamente la misma, excepto que la declaración ahora es un puntero en lugar de una matriz.
Entonces, aquí hay 2 ejemplos que usan notación diferente pero que brindan la misma funcionalidad
y es por eso que ve muchos punteros como parámetros dentro de
un parámetro de función.
Entonces, para resumir, aquí hay algunas cosas que son válidas cuando usa punteros
y cosas que no son válidas.
Entonces, si declaramos algunas variables aquí, declaramos una matriz llamada ganancia y
contiene 3 elementos y luego declaramos 2 punteros.
Ahora en esos punteros, podemos hacer aritmética. Podemos decir puntero uno más más.
Podemos decir que el punto o 2 es igual al punto o uno más 2.
Incluso podemos decir que el puntero 2 es igual a ganar más uno.
Es perfectamente válido hacer eso porque tiene punteros y está modificando los punteros por la dirección,
por lo que puede hacer aritmética de puntos.
No puede hacer aritmética de puntos en matrices. Por lo tanto, no puede decir ganar más más.
No puede decir el puntero 2 0. 2 más 0. 1
porque esas son direcciones.
Y en realidad no está apuntando a
nada dentro de una matriz.
Y no se puede multiplicar puntos de tiempo de ganancia o uno para obtener puntos o 2.
Esos son inválidos.
Por lo tanto, preste atención a la sintaxis correcta para la aritmética
de punteros y también comprenda que la aritmética de puntos solo se puede aplicar a punteros,
no a matrices.
También las funciones que procesan matrices utilizan punteros como argumentos.
Puede elegir entre notación de matriz y notación de puntero para escribir
funciones de procesamiento de matriz.
Entonces, si va a procesar la función aleatoria, está perfectamente bien usar un puntero como parámetro.
Puedes elegir cuál quieres usar.
Pero el uso de punteros suele ser menos código y más eficiente.
El uso de la notación de matrices hace que sea más obvio que la función está
trabajando con matrices y la notación de matrices tiene un aspecto más familiar para los
programadores que tienen experiencia en programación en ciertos lenguajes.
Entonces, si programa antes y Fortran y Pascal y así sucesivamente,
puede usar la notación de flecha.
Otros programadores pueden estar más acostumbrados a trabajar con punteros y pueden encontrar la notación
de punteros más natural, simplemente tiene más sentido.
Está más cerca del lenguaje de máquina usando la aritmética
de puntos y la notación de puntero con algunos compiladores que conduce a un código más
eficiente, otra razón para usarlo.
Así que echemos un vistazo a estos ejemplos dentro de
bloques de código.
Así que aquí está nuestro ejemplo de las diapositivas. Tenemos nuestra declaración de función en la línea 3.
Es una suma de matriz.
Y en este ejemplo, usaremos la notación de matriz.
Entonces usaremos los corchetes cuando usemos índices.
Y lo llamaremos pasar la
matriz de valores y pasar el tamaño.
Entonces, la función de suma de matriz toma una matriz de números enteros. Bueno, lo primero que debe hacer es
crear el puntero que desea usar para la aritmética de puntos
en la línea 14. Y luego debe asignar el final
de la matriz a la matriz de direcciones más el tamaño.
Ese es el final de la matriz, que ahora puede usar para salir del ciclo.
Pero tenemos que asignar el puntero a la matriz.
Sabemos que podemos asignar matrices a punteros para
que apunten al primer elemento simplemente usando el nombre de la matriz.
No tenemos que usar la dirección del operativo.
Podríamos si quisiéramos, de hecho podríamos hacer algo como esto.
Y esto también está bien.
Y luego hacemos más más el puntero. Estamos incrementando el puntero porque todo lo
que está haciendo se incrementa a la siguiente dirección. Apunta al siguiente elemento de la matriz.
Y luego, en la línea 18, estamos desreferenciando el puntero para calcular la suma,
suma igual, suma más el valor del puntero al que apunta.
Entonces, si construimos esto, tenemos una advertencia, que es main no
es un int, queremos cambiar esto porque es
bueno devolver valores de error del main y
simplemente decir return 0.
Podrías regresar si hubo un error en
main, devuelves uno negativo. Ahora ejecutamos esto, verá que solo realiza la suma de los valores
en la matriz, que es 3 más 7 más 9 negativo y así sucesivamente, ni siquiera estoy
seguro de qué es eso, pero parece que es 21.
Ahora podemos modificar fácilmente este parámetro de matriz para
tomar un puntero simplemente declarando el asterisco antes del puntero.
Lo llamamos de la misma manera. Simplemente modificamos. Ya no necesitamos declarar
el puntero. Probablemente queramos cambiar el
nombre para hacerlo más fácil, pero ya no necesitamos declarar este puntero.
Todavía queremos obtener el final de la
matriz y tampoco necesitamos asignarlo más.
Podemos tener algo vacío allí. Y en realidad podría ser más útil tener un ciclo while aquí.
Pero si no tenemos ninguna asignación, podemos poner el punto y coma allí.
Y ahora estamos bien. Todavía queremos quitarlo de referencia y queremos devolverlo.
Pero si
construimos esto, queremos asegurarnos
de definir la declaración de función como un puntero ya que la cambiamos.
Y este puede ser cualquier nombre, pero seremos coherentes.
Ahora que construimos
queremos asegurarnos de que estamos usando nuevamente todas
las variables que cambiamos.
Así que ahora lo construimos con éxito, lo ejecutamos y verá que
obtiene el mismo resultado, que es 21.
Entonces, comprenda esta diferencia entre usar punteros como parámetros formales
en
matrices, puede usarlos indistintamente. Es solo una conveniencia de notación.
Pero normalmente tienes menos código cuando usas un puntero.
Y puede manipularlo más y puede hacer cosas más poderosas, generalmente
también es más eficiente según el compilador. Gracias.