Cómo usar punteros C ++

Cómo usar punteros C ++
La memoria de una computadora es una larga serie de celdas. El tamaño de cada celda se llama byte. Un byte es un espacio ocupado por un personaje 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 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 usando lo que se conoce como referencia. Todavía se puede acceder utilizando un identificador. El enfoque de este artículo está en el uso de punteros y referencias. En C ++, está el objeto puntiagudo y el objeto de puntero. El objeto puntiagudo tiene el objeto de interés. El objeto de puntero tiene la dirección al objeto puntiagudo. El objeto puntero y el objeto puntiagudo, cada uno tiene su identificador. Debe tener conocimientos básicos en C ++, incluidos sus identificadores, funciones y matrices; Para entender este artículo.

La dirección del operador, y

Este es un operador unario. Cuando se le sigue 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) a medida que codifica.

El operador de indirección, *

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

Creando un puntero

Eche un vistazo al siguiente segmento de código:

flotante ptdfloat;
flotante *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, existe 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 flotador. El objeto puntero es siempre del mismo tipo que el objeto puntiagudo. Ptrfoat es un identificador, que solo identifica un objeto de 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 de la dirección del operador, y.

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 usar el operador de indirección en la tercera (última) línea.

El objeto del puntero puede ser declarado e inicializado por el objeto puntiagudo en una declaración, como sigue:

flotante ptdfloat;
float *ptrfoat = &ptdFloat;

La primera línea del segmento de código anterior y este es la misma. Las líneas segunda y tercera del segmento de código anterior se han combinado en una declaración aquí.

Nota En el código anterior que al declarar e inicializar el objeto puntero, el operador de indirección debe usarse. Sin embargo, no se usa si la inicialización se va a hacer después. 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 apuntado por el identificador del 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.

Asignando cero a un puntero

El objeto de puntero siempre debe tener el tipo del objeto puntiagudo. Al declarar el objeto Pointer, el tipo de datos del objeto puntiagudo debe usarse. Sin embargo, el valor de decimal cero 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 llama puntero nulo; es decir, apunta a ninguna parte. Es decir, no tiene la dirección de ningún objeto puntiagudo. Aquí, 0 es decimal cero y no hexadecimal cero. Hexadecimal cero 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, el programa puede compilar, pero puede no ejecutar.

Nombre de la 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 en 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, con la dirección del siguiente elemento en 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 incrementarse. 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 señalar el siguiente elemento de la matriz. PTR ha sido declarado aquí como un objeto de puntero. Sin * aquí, no sería un puntero; Sería un identificador contener un objeto int y no contener 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 la 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';
regresar 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 para el objeto puntiagudo y el identificador para el 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 señale 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 relacionado con una declaración de inicialización de la siguiente manera:

int (*func) () = &fn;

Tenga en cuenta las diferencias y similitudes en los punteros de la función de manejo y los punteros escalar. FUNC es un puntero a una función; Es el objeto puntiagudo; se declara de manera 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, los segundos paréntesis tienen 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;
flotante fn (float fl, int in)

regresar fl;

int main ()

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

La salida es 2.5.

Referencia de C ++

La referencia en C ++ es solo una forma de producir un sinónimo (otro nombre) para un identificador. Utiliza el operador y no de la misma manera que y se usa para 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 es declarado y hecho para mantener el valor, 8. La segunda declaración hace de un nuevo identificador, es 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 necesita precederlo con * . Solo usa el identificador.

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

Las referencias son del mismo tipo.

Referencia a una función

Del mismo modo que 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 de codificar una referencia a un escalar. El siguiente programa ilustra esto:

#incluir
usando el espacio de nombres STD;
flotante fn (float fl, int in)

regresar fl;

int main ()

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

La salida es 2.5.

Tenga en cuenta la primera declaración en la función principal, lo 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 la dirección del operador. Para llamar a la función, solo use cualquier nombre.

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

Función Devolver un puntero

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

#incluir
usando el espacio de nombres STD;
flotante *fn (float fl, int in)

flotante *fll = &fl;
regresar fll;

int main ()

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

La salida es 2.5

La primera declaración en la función, fn () está allí solo para crear un objeto de puntero. Tenga en cuenta el uso único y la posición de * en la firma de la función. Observe también cómo el puntero (dirección) fue recibido en la función Main () por otro objeto Pointer.

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 (FLOAT FL, INT IN)

flotante y frr = fl;
regresar frr;

int main ()

flotante y val = fn (2.5, 6);
cout << val << '\n';
regresar 0;

La salida es 2.5.

La primera declaración en la función, fn () está allí solo para crear una referencia. Tenga en cuenta el uso único y la posición de y en la firma de la función. Observe también 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 puntiagudo, se envía como un argumento a la función:

#incluir
usando el espacio de nombres STD;
FLOAT FN (FLOAT *FL, INT IN)

regresar *fl;

int main ()

flotante V = 2.5;
flotante val = fn (& v, 6);
cout << val << '\n';
regresar 0;

La salida es 2.5

Tenga en cuenta el uso y 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:

flotante *fl = & v;

Tanto FL y V están apuntando al mismo objeto puntiagudo que contiene 2.5. *FL en la declaración de devolución no es una declaración; significa que el valor del objeto puntiagudo apuntado por el objeto de puntero.

Pasando 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;
FLOAT FN (FLOAT & FL, INT IN)

regresar fl;

int main ()

flotante V = 2.5;
flotante val = fn (v, 6);
cout << val << '\n';
regresar 0;

La salida es 2.5

Tenga en cuenta el uso y la posición de y 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:

flotante y 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 [])

regresar arra [2];

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
cout << val << '\n';
regresar 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 de 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 [])

regresar arra;

int main ()

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

Puntero de un puntero

Un puntero puede apuntar a otro puntero. Es decir, un objeto de puntero puede tener la dirección de otro objeto de puntero. Todavía 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 Pointer-To Pointer, se usa Double *. Para devolver el valor del objeto puntiagudo final, todavía se usa doble *.

Variedad 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';
regresar 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 Pointers of Pointers, dos * están involucrados. En el caso de la matriz de punteros, uno * ya ha sido atendido, porque el identificador de la matriz es un puntero.

Matriz de cuerdas de longitud variable

Un literal de cadenas es una constante que devuelve un puntero. Una matriz de cadenas de longitud variable es una variedad de punteros. Cada valor en la matriz es un puntero. Los punteros son direcciones a ubicaciones de memoria y son del mismo tamaño. Las cadenas de las 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';
regresar 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 personaje, 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, entonces 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 = #
regresar inter;

int main ()

int *( *func) () = &fn;
int val = *func ();
cout << val << '\n';
regresar 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 precedió a un asterisco. La primera declaración en la función main () ilustra esto. Para llamar a la función usando el puntero, precedirlo con *.

Conclusión

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

flotante puntiagudo;
Float *Pointer = &pointed;

* tiene dos significados: en una declaración, está indicando 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.

y 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,

float (& reffunc) (float, 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 punto necesita dos * en lugar de uno, cuando sea apropiado.