Saltar al contenido

Punteros en C: ¿cuándo usar el ampersand y el asterisco?

Nuestros mejores investigadores han agotado sus reservas de café, por su búsqueda diariamente por la resolución, hasta que Rubén encontró la solución en Gogs así que hoy la compartimos aquí.

Solución:

Tienes punteros y valores:

int* p; // variable p is pointer to integer type
int i; // integer value

Conviertes un puntero en un valor con *:

int i2 = *p; // integer i2 is assigned with integer value that pointer p is pointing to

Conviertes un valor en un puntero con &:

int* p2 = &i; // pointer p2 will point to the address of integer i

Editar: en el caso de las matrices, se tratan como punteros. Si piensa en ellos como punteros, utilizará * para obtener los valores dentro de ellos como se explicó anteriormente, pero también hay otra forma más común de usar el [] operador:

int a[2];  // array of integers
int i = *a; // the value of the first element of a
int i2 = a[0]; // another way to get the first element

Para obtener el segundo elemento:

int a[2]; // array
int i = *(a + 1); // the value of the second element
int i2 = a[1]; // the value of the second element

Entonces el [] El operador de indexación es una forma especial de * operador, y funciona así:

a[i] == *(a + i);  // these two statements are the same thing

Hay un patrón cuando se trata de matrices y funciones; es un poco difícil de ver al principio.

Cuando se trata de matrices, es útil recordar lo siguiente: cuando un array expresión aparece en la mayoría de los contextos, el tipo de expresión se convierte implícitamente de “N-element array de T “a” puntero a T “, y su valor se establece para apuntar al primer elemento en el array. Las excepciones a esta regla son cuando el array La expresión aparece como un operando de la & o sizeof operadores, o cuando es un string literal que se utiliza como inicializador en una declaración.

Por tanto, cuando llamas a una función con un array expresión como argumento, la función recibirá un puntero, no un array:

int arr[10];
...
foo(arr);
...

void foo(int *arr)  ... 

Es por eso que tu no utilizar el & operador para argumentos correspondientes a “% s” en scanf():

char str[STRING_LENGTH];
...
scanf("%s", str);

Debido a la conversión implícita, scanf() recibe un char * valor que apunta al comienzo de la str array. Esto sostiene true para cualquier función llamada con un array expresión como argumento (casi cualquiera de los str* funciones *scanf y *printf funciones, etc.).

En la práctica, probablemente nunca llamará a una función con un array expresión usando la & operador, como en:

int arr[N];
...
foo(&arr);

void foo(int (*p)[N]) ...

Este código no es muy común; tienes que saber el tamaño del array en la declaración de la función, y la función solo funciona con punteros a matrices de tamaños específicos (un puntero a un elemento de 10 array de T es un tipo diferente que un puntero a un elemento de 11 array de T).

Cuando un array La expresión aparece como un operando a la & operador, el tipo de la expresión resultante es “puntero al elemento N array de T “, o T (*)[N], que es diferente de un array de punterosT *[N]) y un puntero al tipo base (T *).

Cuando se trata de funciones y punteros, la regla a recordar es: si desea cambiar el valor de un argumento y que se refleje en el código de llamada, debe pasar un puntero a lo que desea modificar. Una vez más, las matrices son un poco complicadas, pero primero nos ocuparemos de los casos normales.

Recuerda que C pasa todos argumentos de función por valor; el parámetro formal recibe una copia del valor en el parámetro real, y cualquier cambio en el parámetro formal no se refleja en el parámetro real. El ejemplo común es una función de intercambio:

void swap(int x, int y)  int tmp = x; x = y; y = tmp; 
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %dn", a, b);
swap(a, b);
printf("after swap: a = %d, b = %dn", a, b);

Obtendrá el siguiente resultado:

before swap: a = 1, b = 2
after swap: a = 1, b = 2

Los parámetros formales x y y son objetos distintos de a y b, así que cambia a x y y no se reflejan en a y b. Dado que queremos modificar los valores de a y b, debemos pasar punteros para ellos a la función de intercambio:

void swap(int *x, int *y) int tmp = *x; *x = *y; *y = tmp; 
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %dn", a, b);
swap(&a, &b);
printf("after swap: a = %d, b = %dn", a, b);

Ahora tu salida será

before swap: a = 1, b = 2
after swap: a = 2, b = 1

Tenga en cuenta que, en la función de intercambio, no cambiamos los valores de x y y, pero los valores de lo que x y yapunta a. Escribiendo a *x es diferente de escribir para x; no estamos actualizando el valor en x en sí, obtenemos una ubicación de x y actualice el valor en esa ubicación.

Esto es igualmente true si queremos modificar un valor de puntero; si escribimos

int myFopen(FILE *stream) stream = fopen("myfile.dat", "r"); 
...
FILE *in;
myFopen(in);

entonces estamos modificando el valor del parámetro de entrada stream, no lo que streampuntos a, tan cambiante stream no tiene ningún efecto sobre el valor de in; para que esto funcione, debemos pasar un puntero al puntero:

int myFopen(FILE **stream) *stream = fopen("myFile.dat", "r"); 
...
FILE *in;
myFopen(&in);

Una vez más, los arreglos arrojan un poco de una llave inglesa a las obras. Cuando pasas un array expresión a una función, lo que recibe la función es un puntero. Por como array subíndice está definido, puede usar un operador de subíndice en un puntero de la misma manera que lo puede usar en un array:

int arr[N];
init(arr, N);
...
void init(int *arr, int N) size_t i; for (i = 0; i < N; i++) arr[i] = i*i;

Tenga en cuenta que array no se pueden asignar objetos; es decir, no puedes hacer algo como

int a[10], b[10];
...
a = b;

por lo que debe tener cuidado cuando se trata de punteros a matrices; algo como

void (int (*foo)[N])

  ...
  *foo = ...;

no funcionará.

En pocas palabras

  • & significa el Dirección de, verá que en los marcadores de posición para que las funciones modifiquen la variable de parámetro como en C, las variables de parámetro se pasan por valor, usando los medios y ampersand para pasar por referencia.
  • * significa el desreferencia de una variable de puntero, lo que significa obtener el valor de esa variable de puntero.
int foo(int *x)
   *x++;


int main(int argc, char **argv)
   int y = 5;
   foo(&y);  // Now y is incremented and in scope here
   printf("value of y = %dn", y); // output is 6
   /* ... */

El ejemplo anterior ilustra cómo llamar a una función foo mediante el uso de paso por referencia, compare con este

int foo(int x)
   x++;


int main(int argc, char **argv)
   int y = 5;
   foo(y);  // Now y is still 5
   printf("value of y = %dn", y); // output is 5
   /* ... */

Aquí hay una ilustración del uso de un desreferencia

int main(int argc, char **argv)
   int y = 5;
   int *p = NULL;
   p = &y;
   printf("value of *p = %dn", *p); // output is 5

Lo anterior ilustra cómo obtuvimos el Dirección dey y lo asignó a la variable de puntero p. Entonces nosotros desreferenciap adjuntando el * al frente para obtener el valor de p, es decir *p.

Agradecemos que desees añadir valor a nuestra información asistiendo con tu experiencia en las ilustraciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *