El puntero C ++ se pasa como un parámetro de función [C ++]

Transferencia desde: http://blog.csdn.net/fjb2080/article/details/5623427

 

Artículo original, indique la fuente para la reimpresión, ¡gracias!
Autor: Lin Qing, nombre del blog: Du Jing vuela vacía

 

Dirección del blog: http://blog.csdn.net/fjb2080

 

De hecho, para C o C ++, se estima que la parte más difícil es el puntero. El puntero es poderoso, pero también es un lugar donde muchas personas lo llevan.

 

 

Hace algún tiempo, escribió un artículo " C  arreglos y apuntadores ++ similitudes y diferencias  " para los punteros de C y C ++ hicieron una explicación preliminar. Esta vez explicaré el problema de pasar punteros como parámetros de función.

 

Muchas personas están familiarizadas con el uso de punteros, pero a menudo se incluyen en el problema de los punteros porque no entienden la naturaleza de los punteros. De hecho, si comprende la naturaleza de los punteros, el uso de los punteros será claro.

 

Como principiante en C, a menudo encuentro dos problemas clásicos de pasar punteros como parámetros de función. Aquí, explicaré estos dos problemas a través de la esencia del puntero, así que no importa qué tipo de problema de puntero encuentre en el futuro, si analiza el puntero de esta manera, ¡puede resolverse!

 

Primero, la primera pregunta es esta:

Escriba una función para intercambiar los valores en los dos parámetros.

 

Los principiantes a menudo escriben:

 

intercambio nulo (int x, int y)

{

int p = x;

x = y;

y = p;

}

 

Después de eso, encontrará información para comprender que debe escribirse así:

intercambio nulo (int * x, int * y)

{

int * p = x;

*x = *y;

* y = * p;

}

 

El segundo problema es escribir una función que asigne memoria a un puntero:

Los principiantes a menudo escriben de esta manera:

void my_malloc (void * p, int size)

{

p = malloc (sizeof (int) * size);

}

 

Luego verifiqué la información y supe que debería escribirse así:

void my_malloc (void ** p, int size)

{

* p = malloc (sizeof (int) * size);

}

 

Aunque hay muchas discusiones de este tipo en Internet, y muchas personas han hecho muchas explicaciones, nunca han podido dar una declaración clara y que pueda recordarse durante mucho tiempo. Una comprensión de principios!

 

En primer lugar, debe recordar que los  punteros, como las variables, tienen direcciones, pero el valor de la variable se interpreta como un valor y el valor del puntero se interpreta como una dirección.

 

A continuación, miramos el código:

vacío principal()

{

int x;

int * p;

}

 

Nos fijamos en la estructura de la memoria de esta función:

 

Esta es una estructura de pila de una función, podemos ver que tanto las variables como los punteros ocupan 4 bytes. Además, debido a que no los hemos inicializado, el contenido de la variable x y el puntero p son aleatorios, es decir, el valor de x es incierto, p puede apuntar a una determinada dirección de memoria, si ahora opera en p puede causar El programa se bloquea.

 

De hecho, recordamos que el puntero también tiene  el concepto de dirección y se resolvieron muchos problemas.

 

A continuación, permítanme analizar la situación en la que se pasa el puntero como parámetro de función.

Si nuestro código se ve así, ¿qué verá?

 

int main (int argc, char * argv [])

{

int * a = nuevo int (10);

func (a);

 

devuelve 0;

}

 

Lo primero que hay que decir es, por supuesto: los punteros también tienen direcciones.

La segunda cosa que decir es: cuando se pasa una variable a un parámetro de función, esta variable se copia.

 

Para el segundo punto, debemos entender cuando entendemos que la función de intercambio vacío (int x, int y) quiere intercambiar los valores de estas dos variables.

Por ejemplo:

int a;

int b;

intercambio (a, b);

Los valores de ayb no pueden intercambiarse, porque en este momento ayb en intercambio (a, b) no son las variables ayb originales, solo se copian.

 

Con estos dos conceptos, no es difícil entender el problema de pasar punteros como parámetros de función.

 

Primero, veamos la estructura de memoria de un puntero y un puntero p en el código anterior.

Vemos que cuando usamos a como parámetro de la función func, la función copia el puntero, pero el contenido de los dos punteros es el mismo, es decir, apuntan a la misma memoria, es decir, 10.

 

Si no lo comprende, lo explicaré mediante un código y probaré:

 

 

[cpp]   ver   copia simple
 
 
  1. #include <stdio.h>  
  2.  func nulo ( int * p)  
  3. {  
  4.     printf ( "* p =% d / n" , * p);  
  5.     printf ( "& p =% p / n" , & p);  
  6. }  
  7. int  main ( int  argc,  char  * argv [])  
  8. {  
  9.     int  * a =  nuevo  int (10);  
  10.     printf ( "* a =% d / n" , * a);  
  11.     printf ( "& a =% p / n" , & a);  
  12.     func (a);  
  13.     devuelve  0;  
  14. }  

 

 

 

Compilar: g ++ -g -Wall test1.cpp

Ejecutar: ./a.out

Salida:

* a = 10

& a = 0xbfd4447c

* p = 10

& p = 0xbfd44460

 

Vemos la salida, el valor de la dirección señalada por a es el mismo que el valor de la dirección señalada por p, ambos son 10. Sin embargo, para los punteros ayp, sus propias direcciones son diferentes, por lo que vemos que la función func copia el puntero aa P. Tienen el mismo valor, pero tienen direcciones diferentes y son punteros diferentes.

 

Vamos más allá:

 

[cpp]   ver   copia simple
 
 
  1. #include <stdio.h>  
  2.  func nulo ( int * p)  
  3. {  
  4.     printf ( "* p =% d / n" , * p);  
  5.     printf ( "& p =% p / n" , & p);  
  6.     printf ( "& * p =% p / n" , & * p);  
  7. }  
  8. int  main ( int  argc,  char  * argv [])  
  9. {  
  10.     int  * a =  nuevo  int (10);  
  11.     printf ( "* a =% d / n" , * a);  
  12.     printf ( "& a =% p / n" , & a);  
  13.     printf ( "& * a =% p / n" , & * a);  
  14.     func (a);  
  15.     devuelve  0;  
  16. }  

 

 

 

Compilar salida:

* a = 10

& a = 0xbfe1c77c

& * a = 0x94b6008

* p = 10

& p = 0xbfe1c760

& * p = 0x94b6008

 

Podemos ver también que el valor de la dirección de un puntero es la dirección y los puntos de valor p puntero a es el mismo, son 0x94b6008, tal como se muestra arriba, con el fin de profundizar en la impresión, y luego mirar a esta tabla  , a continuación, de nuevo Compare la salida del programa  y luego experimente los dos puntos que mencioné anteriormente  : Un punto es: el puntero tiene una dirección  . Otro punto es: los parámetros de la función se copiaron en el pasado  .

 

 

 

Hablando de eso, volvamos a los dos problemas mencionados al principio del artículo, uno es el problema del intercambio:

 

intercambio nulo (int * x, int * y)

{

int * p = x;

*x = *y;

* y = * p;

}

 

Entonces, ¿por qué se puede cambiar esto?

int a = 2;

int b = 3;

intercambio (& a, & b);

 

Cuando pasamos las direcciones a y b a la función de intercambio, la función copió las dos direcciones y las asignó a los dos punteros x e Y. Estos dos punteros apuntan a las variables a y b. Sus gráficos son los siguientes:

 

Entonces, cuando desreferenciamos los punteros:

int * p = x;

*x = *y;

* y = * p;

 

Operamos con los valores de las variables en a y b, por lo que intercambiamos los valores de a y b con éxito.

 

Veamos la segunda pregunta:

void my_malloc (void * p, int size)

{

p = malloc (sizeof (int) * size);

}

Cuando este es el caso:

int * a;

my_malloc (a, 10);

¿Por qué falla esto?

 

A continuación, déjame analizar:

Cuando llamamos a my_malloc (a, 10); function, y la función no se ha ejecutado hasta la declaración p = malloc (size); la situación es la siguiente:

 

Vemos que los valores de los punteros de a y p son los mismos, ambos apuntan a una dirección indefinida.

En este momento, ejecutamos esta declaración:

p = malloc (sizeof (int) * size);

Dividamos esta declaración en dos partes: una es ejecutar malloc (sizeof (int) * size) primero, luego ejecutar la declaración de asignación y pagar el valor de retorno de malloc (sizeof (int) * size) a p

El primer paso: primero ejecute malloc (sizeof (int) * size); (Aquí solo consideramos la asignación exitosa de memoria por malloc)

 

Paso 2: Pague el valor de retorno de ejecutar malloc (sizeof (int) * size) a p, como se muestra a continuación:

 

De la imagen de arriba, podemos saber que es por eso que todavía no podemos asignar una dirección a a.

 

Analicemos esto a continuación:

void my_malloc (void ** p, int size)

{

* p = malloc (sizeof (int) * size);

}

 

int * a;

my_malloc (& a, 10);

¿Por qué tienes éxito de esta manera?

 

 

Vemos que cuando se ejecuta la función

my_malloc (void ** p, int size);

Pero no ha sido implementado

* p = malloc (sizeof (int) * size);

Declaraciones, su diagrama de estructura de memoria es el siguiente:

 

De hecho, aquí, podemos tratar punteros bidimensionales y punteros unidimensionales como variables, y también tienen direcciones. Es solo que su explicación es diferente.

Variable: el valor dentro es un valor numérico.

Puntero unidimensional: el valor dentro es una dirección, y el valor en esta dirección es un valor numérico.

Puntero bidimensional: el valor dentro es una dirección, y el valor en esta dirección también es una dirección.

 

Entonces, miré la imagen para explicar p:

p es una dirección, esta dirección es & a, que es el valor de dirección del puntero a, y el valor en la dirección del puntero a también es una dirección. Esta dirección apunta a un lugar incierto. ¡La comprensión será buena!

 

La figura después de ejecutar malloc (tamaño) es la siguiente:

 

Luego ejecute la declaración de asignación:

* p = malloc (sizeof (int) * size);

Después, como se muestra a continuación:

 

Luego, asignamos memoria para apuntar con éxito.

 

La dirección de descarga en pdf de este artículo: El problema del paso del puntero c ++ como una función parameter.pdf

Publicado 36 artículos originales · elogiado 17 · visitas 6274

Supongo que te gusta

Origin blog.csdn.net/qq_39248307/article/details/79779670
Recomendado
Clasificación