C ++

Cómo utilizar los punteros de C ++

Cómo utilizar los punteros de C ++
La memoria de una computadora es una larga serie de células. El tamaño de cada celda se llama byte. Un byte es un espacio ocupado por un carácter inglés del alfabeto. Un objeto en el sentido ordinario es un conjunto consecutivo de bytes en la memoria. Cada celda tiene una dirección, que es un número entero, generalmente escrito en forma hexadecimal. Hay tres formas de acceder a un objeto en la memoria. Se puede acceder a un objeto utilizando lo que se conoce como puntero. Se puede acceder utilizando lo que se conoce como referencia. Todavía se puede acceder mediante un identificador. El enfoque de este artículo es el uso de punteros y referencias. En C ++, existe el objeto puntiagudo y el objeto puntero. El objeto puntiagudo tiene el objeto de interés. El objeto puntero tiene la dirección del objeto puntiagudo.

Debe tener conocimientos básicos en C ++, incluidos sus identificadores, funciones y matrices; para entender este artículo.

El objeto puntero y el objeto puntiagudo, cada uno tiene su identificador.

La dirección del operador, y

Este es un operador unario. Cuando va seguido de un identificador, devuelve la dirección del objeto del identificador. Considere la siguiente declaración:

int ptdInt;

A continuación se muestra el código, la siguiente expresión, devolverá la dirección identificada por ptdInt:

& ptdInt

No necesita saber la dirección exacta (número) mientras codifica.

El Operador de Indirección, *

Este es un operador unario en el contexto de punteros. Por lo general, se escribe delante de un identificador. Si se usa en una declaración del identificador, entonces el identificador es el objeto puntero que contiene solo la dirección del objeto puntiagudo. Si se usa delante del identificador del objeto puntero, para devolver algo, entonces la cosa devuelta es el valor del objeto puntiagudo.

Crear un puntero

Eche un vistazo al siguiente segmento de código:

float ptdFloat;
float * ptrFloat;
ptrFoat = &ptdFloat;

El segmento comienza con la declaración del objeto puntiagudo, ptdFloat. ptdFloat es un identificador, que solo identifica un objeto flotante. Se le podría haber asignado un objeto real (valor), pero en este caso, no se le ha asignado nada. A continuación, en el segmento, está la declaración del objeto puntero. El operador de indirección frente a este identificador significa que debe contener la dirección de un objeto puntiagudo. El tipo de objeto, flotante al comienzo de la declaración, significa que el objeto puntiagudo es un flotante. El objeto puntero es siempre del mismo tipo que el objeto puntiagudo. ptrFoat es un identificador, que solo identifica un objeto puntero.

En la última declaración del código, la dirección del objeto puntiagudo se asigna al objeto puntero. Tenga en cuenta el uso del operador de dirección de, &.

La última declaración (línea) anterior muestra que después de declarar el objeto puntero sin inicialización, no necesita el operador de indirección, cuando tiene que inicializarlo. De hecho, es un error de sintaxis utilizar el operador de indirección en la tercera (última) línea.

El objeto apuntador puede ser declarado e inicializado por el objeto apuntado en una declaración, como sigue:

float ptdFloat;
flotar * ptrFoat = &ptdFloat;

La primera línea del segmento de código anterior y este, son iguales. La segunda y tercera líneas del segmento de código anterior se han combinado en una declaración aquí.

Tenga en cuenta en el código anterior que al declarar e inicializar el objeto puntero, se debe utilizar el operador de indirección. Sin embargo, no se utiliza si la inicialización se va a realizar posteriormente. El objeto puntero se inicializa con la dirección del objeto puntiagudo.

En el siguiente segmento de código, el operador de indirección se usa para devolver el contenido del objeto puntiagudo.

int ptdInt = 5;
int * ptrInt = &ptdInt;
cout << *ptrInt << '\n';

La salida es 5.

En la última declaración aquí, el operador de indirección se ha utilizado para devolver el valor al que apunta el identificador de puntero. Entonces, cuando se usa en una declaración, el identificador para el operador de indirección contendría la dirección del objeto puntiagudo. Cuando se usa en una expresión de retorno, en combinación con el identificador de puntero, el operador de indirección devuelve el valor del objeto puntiagudo.

Asignar cero a un puntero

El objeto puntero siempre debe tener el tipo de objeto puntiagudo. Al declarar el objeto puntero, se debe utilizar el tipo de datos del objeto apuntado. Sin embargo, el valor del cero decimal se puede asignar al puntero como en el siguiente segmento de código:

int ptdInt = 5;
int * ptrInt;
ptrInt = 0;
o en el segmento,
int ptdInt = 5;
int * ptrInt = 0;

En cualquier caso, el puntero (identificador) se denomina puntero nulo; es decir, apunta a ninguna parte. Es decir, no tiene la dirección de ningún objeto puntiagudo. Aquí, 0 es cero decimal y no cero hexadecimal. El cero hexadecimal apuntaría a la primera dirección de la memoria de la computadora.

No intente obtener el valor apuntado por un puntero nulo. Si lo intenta, es posible que el programa se compile, pero es posible que no se ejecute.

Nombre de matriz como puntero constante

Considere la siguiente matriz:

int arr [] = 000, 100, 200, 300, 400;

El nombre de la matriz, arr es en realidad el identificador que tiene la dirección del primer elemento de la matriz. La siguiente expresión devuelve el primer valor de la matriz:

* arr

Con la matriz, el operador de incremento, ++ se comporta de manera diferente. En lugar de agregar 1, reemplaza la dirección del puntero por la dirección del siguiente elemento de la matriz. Sin embargo, el nombre de la matriz es un puntero constante; lo que significa que su contenido (dirección) no se puede cambiar o incrementar. Entonces, para incrementar, la dirección de inicio de la matriz debe asignarse a un puntero no constante de la siguiente manera:

int * ptr = arr;

Ahora, ptr se puede incrementar para apuntar al siguiente elemento de la matriz. ptr se ha declarado aquí como un objeto puntero. Sin * aquí, no sería un puntero; sería un identificador para contener un objeto int y no para mantener una dirección de memoria.

El siguiente segmento de código finalmente apunta al cuarto elemento:

++ptr;
++ptr;
++ptr;

El siguiente código genera el cuarto valor de la matriz:

int arr [] = 000, 100, 200, 300, 400;
int * ptr = arr;
++ptr;
++ptr;
++ptr;
cout << *ptr << '\n';

La salida es 300.

Nombre de función como identificador

El nombre de una función es el identificador de la función. Considere la siguiente definición de función:

int fn ()

cout << "seen" << '\n';
volver 4;

fn es el identificador de la función. La expresion,

& fn

devuelve la dirección de la función en la memoria. fn es como el objeto puntiagudo. La siguiente declaración declara un puntero a una función:

int (* func) ();

El identificador del objeto puntiagudo y el identificador del objeto puntero es diferente. func es un puntero a una función. fn es el identificador de una función. Y así, se puede hacer que func apunte a fn de la siguiente manera:

func = &fn;

El valor (contenido) de func es la dirección de fn. Los dos identificadores podrían haberse vinculado con una declaración de inicialización de la siguiente manera:

int (* func) () = &fn;

Tenga en cuenta las diferencias y similitudes en el manejo de punteros de función y punteros escalares. func es un puntero a una función; es el objeto puntiagudo; se declara de forma diferente a un puntero escalar.

La función se puede llamar con,

fn ()
o
func ()

No se puede llamar con * func ().

Cuando la función tiene parámetros, el segundo paréntesis tiene los tipos de parámetros y no necesita tener los identificadores para los parámetros. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres std;
flotar fn (flotar fl, int en)

return fl;

int main ()

float (* func) (float, int) = &fn;
float val = func (2.5, 6);
cout << val << '\n';
return 0;

La salida es 2.5.

Referencia de C ++

Hacer referencia en C ++ es solo una forma de producir un sinónimo (otro nombre) para un identificador. Utiliza el operador &, pero no de la misma forma que & se utiliza para los punteros. Considere el siguiente segmento de código:

int myInt = 8;
int & yourInt = myInt;
cout << myInt << '\n';
cout << yourInt << '\n';

La salida es:

8
8

La primera declaración inicializa el identificador, myInt; I.mi. myInt se declara y se hace para mantener el valor, 8. La segunda declaración crea un nuevo identificador, yourInt un sinónimo de myInt. Para lograr esto, el operador & se coloca entre el tipo de datos y el nuevo identificador en la declaración. Las declaraciones de cout muestran que los dos identificadores son sinónimos. Para devolver el valor en este caso, no es necesario que lo anteponga * . Solo usa el identificador.

myInt y yourInt aquí, no son dos objetos diferentes. Son dos identificadores diferentes que hacen referencia (identifican) la misma ubicación en la memoria que tiene el valor 8. Si se cambia el valor de myInt, el valor de yourInt también cambiará automáticamente. Si se cambia el valor de yourInt, el valor de myInt también cambiará automáticamente.

Las referencias son del mismo tipo.

Referencia a una función

Así como puede tener una referencia a un escalar, también puede tener una referencia a una función. Sin embargo, codificar una referencia a una función es diferente a codificar una referencia a un escalar. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres std;
flotar fn (flotar fl, int en)

return fl;

int main ()

flotar (& func) (flotar, int) = fn;
float val = func (2.5, 6);
cout << val << '\n';
return 0;

La salida es 2.5.

Tenga en cuenta la primera declaración en la función principal, que hace que func sea un sinónimo de fn. Ambos hacen referencia a la misma función. Tenga en cuenta el uso único y la posición de &. Entonces & es el operador de referencia aquí y no el operador de dirección. Para llamar a la función, simplemente use cualquier nombre.

Un identificador de referencia no es lo mismo que un identificador de puntero.

Función que devuelve un puntero

En el siguiente programa, la función devuelve un puntero, que es la dirección del objeto señalado:

#incluir
usando el espacio de nombres std;
flotar * fn (flotar fl, int en)

flotar * fll = &fl;
return fll;

int main ()

flotar * val = fn (2.5, 6);
cout << *val << '\n';
return 0;

La salida es 2.5

La primera instrucción en la función, fn () está ahí solo para crear un objeto puntero. Tenga en cuenta el uso único y la posición de * en la firma de la función. También observe cómo el puntero (dirección) fue recibido en la función main () por otro objeto puntero.

Función que devuelve una referencia

En el siguiente programa, la función devuelve una referencia:

#incluir
usando el espacio de nombres std;
float & fn (flotador fl, int in)

flotar & frr = fl;
return frr;

int main ()

flotar & val = fn (2.5, 6);
cout << val << '\n';
return 0;

La salida es 2.5.

La primera declaración en la función, fn () está ahí solo para crear una referencia. Tenga en cuenta el uso único y la posición de & en la firma de la función. También observe cómo la referencia, fue recibida en la función main () por otra referencia.

Pasar un puntero a una función

En el siguiente programa, un puntero, que en realidad es la dirección de un objeto con punta flotante, se envía como argumento a la función:

#incluir
usando el espacio de nombres std;
flotar fn (flotar * fl, int en)

return * fl;

int main ()

flotar v = 2.5;
flotador val = fn (& v, 6);
cout << val << '\n';
return 0;

La salida es 2.5

Tenga en cuenta el uso y la posición de * para el parámetro flotante en la firma de la función. Tan pronto como se inicia la evaluación de la función fn (), se realiza la siguiente declaración:

flotar * fl = & v;

Tanto fl como & v apuntan al mismo objeto puntiagudo que contiene 2.5. * fl en la declaración de retorno no es una declaración; es decir, el valor del objeto puntiagudo al que apunta el objeto puntero.

Pasar una referencia a una función

En el siguiente programa, se envía una referencia como argumento a la función:

#incluir
usando el espacio de nombres std;
flotar fn (flotar y fl, int en)

return fl;

int main ()

flotar v = 2.5;
flotador val = fn (v, 6);
cout << val << '\n';
return 0;

La salida es 2.5

Tenga en cuenta el uso y la posición de & para el parámetro flotante en la firma de la función. Tan pronto como se inicia la evaluación de la función fn (), se realiza la siguiente declaración:

flotar & fl = v;

Pasar una matriz a una función

El siguiente programa muestra cómo pasar una matriz a una función:

#incluir
usando el espacio de nombres std;
int fn (int arra [])

return arra [2];

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
cout << val << '\n';
return 0;

La salida es 200.

En este programa, es la matriz que se pasa. Tenga en cuenta que el parámetro de la firma de la función tiene una declaración de matriz vacía. El argumento en la llamada a la función es solo el nombre de una matriz creada.

¿Puede una función C ++ devolver una matriz??

Una función en C ++ puede devolver el valor de una matriz, pero no puede devolver la matriz. La compilación del siguiente programa da como resultado un mensaje de error:

#incluir
usando el espacio de nombres std;
int fn (int arra [])

return arra;

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
return 0;

Puntero de un puntero

Un puntero puede apuntar a otro puntero. Es decir, un objeto puntero puede tener la dirección de otro objeto puntero. Todos deben ser del mismo tipo. El siguiente segmento de código ilustra esto:

int ptdInt = 5;
int * ptrInt = &ptdInt;
int ** ptrptrInt = &ptrInt;
cout << **ptrptrInt << '\n';

La salida es 5.

En la declaración de puntero a puntero, se usa doble *. Para devolver el valor del objeto puntiagudo final, todavía se usa double *.

Matriz de punteros

El siguiente programa muestra cómo codificar una matriz de punteros:

#incluir
usando el espacio de nombres std;
int main ()

int num0 = 000, num1 = 100, num2 = 200, num3 = 300, num4 = 400;
int * no0 = & num0, * no1 = & num1, * no2 = & num2, * no3 = & num3, * no4 =&num4;
int * arr [] = no0, no1, no2, no3, no4;
cout << *arr[4] << '\n';
return 0;

La salida es:

400

Tenga en cuenta el uso y la posición de * en la declaración de la matriz. Tenga en cuenta el uso de * al devolver un valor en la matriz. Con punteros de punteros, hay dos * involucrados. En el caso de una matriz de punteros, uno * ya ha sido atendido, porque el identificador de la matriz es un puntero.

Matriz de cadenas de longitud variable

Un literal de cadena es una constante que devuelve un puntero. Una matriz de cadenas de longitud variable es una matriz de punteros. Cada valor de la matriz es un puntero. Los punteros son direcciones a ubicaciones de memoria y tienen el mismo tamaño. Las cadenas de diferentes longitudes están en otra parte de la memoria, no en la matriz. El siguiente programa ilustra el uso:

#incluir
usando el espacio de nombres std;
int main ()

const char * arr [] = "mujer", "niño", "niña", "adulto";
cout << arr[2] << '\n';
return 0;

La salida es "niña".

La declaración de la matriz comienza con la palabra reservada, "const" para constante; seguido de "char" para el carácter, luego el asterisco, * para indicar que cada elemento es un puntero. Para devolver una cadena de la matriz, * no se usa, debido a la naturaleza implícita del puntero de cada cadena. Si se usa *, se devolverá el primer elemento de la cadena.

Puntero a una función que devuelve un puntero

El siguiente programa ilustra cómo se codifica un puntero a una función que devuelve un puntero:

#incluir
usando el espacio de nombres std;
int * fn ()

int num = 4;
int * inter = #
volver inter;

int main ()

int * (* func) () = &fn;
int val = * func ();
cout << val << '\n';
return 0;

La salida es 4.

La declaración de un puntero a una función que devuelve un puntero es similar a la declaración de un puntero a una función ordinaria pero precedida por un asterisco. La primera declaración en la función main () ilustra esto. Para llamar a la función usando el puntero, preceda con *.

Conclusión

Para crear un puntero a un escalar, haga algo como,

flotador puntiagudo;
flotador * puntero = &pointed;

* tiene dos significados: en una declaración, indica un puntero; para devolver algo, es por el valor del objeto puntiagudo.

El nombre de la matriz es un puntero constante al primer elemento de la matriz.

Para crear un puntero a una función, puede hacer,

int (* func) () = &fn;

donde fn () es una función definida en otro lugar y func es el puntero.

& tiene dos significados: en una declaración, indica una referencia (sinónimo) al mismo objeto que otro identificador; al devolver algo, significa la dirección de.

Para crear una referencia a una función, puede hacer,

flotar (& refFunc) (flotar, int) = fn;

donde fn () es una función definida en otro lugar y refFunc es la referencia.

Cuando una función devuelve un puntero, el valor devuelto debe ser recibido por un puntero. Cuando una función devuelve una referencia, el valor devuelto debe ser recibido por una referencia.

Al pasar un puntero a una función, el parámetro es una declaración, mientras que el argumento es la dirección de un objeto puntiagudo. Al pasar una referencia a una función, el parámetro es una declaración, mientras que el argumento es la referencia.

Al pasar una matriz a una función, el parámetro es una declaración mientras que el argumento es el nombre de la matriz sin []. La función C ++ no devuelve una matriz.

Un puntero a puntero necesita dos * en lugar de uno, cuando corresponda.

Chrys

Cómo instalar y jugar a Doom en Linux
Introducción a Doom La serie Doom se originó en los años 90 después del lanzamiento del Doom original. Fue un éxito instantáneo y, desde ese momento e...
Vulkan para usuarios de Linux
Con cada nueva generación de tarjetas gráficas, vemos que los desarrolladores de juegos superan los límites de la fidelidad gráfica y se acercan un pa...
OpenTTD frente a Simutrans
Crear su propia simulación de transporte puede ser divertido, relajante y extremadamente atractivo. Es por eso que debes asegurarte de probar tantos j...