• Domingo 17 de Noviembre de 2024, 20:24

Autor Tema:  Operadores De Indirección (*), De Dirección (&)...  (Leído 7413 veces)

JoRDi-18

  • Miembro activo
  • **
  • Mensajes: 40
    • Ver Perfil
Operadores De Indirección (*), De Dirección (&)...
« en: Viernes 6 de Febrero de 2004, 13:35 »
0
Hola:

Bueno, al parecer el lío que tenía de los operadores de indirección y dirección es aún mayor del que pensaba...

Me gustaría que me explicaseis cómo se útilizan, con qué se puede utilizar, etc. Algo general. Y si fueseis tan amable de poner algunos buenos apuntes de Internet que traten este apartado os lo agradecería muchísimo.
[size=109]Pensamientos elevados deben tener un lenguaje elevado.[/size]
Llamamé Jordi. Cuando me llames así, sonríe.

CiRRuS

  • Miembro MUY activo
  • ***
  • Mensajes: 218
    • Ver Perfil
    • http://zirrus.es
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #1 en: Viernes 6 de Febrero de 2004, 13:52 »
0
Como primera aproximacion:

- Operador *: Se usa para la definición de punteros y para obtener el valor de lo apuntado por un puntero. Un puntero es una variable que guarda la dirección de memoria de una variable del mismo tipo del que se ha definido el puntero. Pa no liarte, puedes traducirlo como "a lo que apunta..."
Código: Text
  1.  
  2. int *i;
  3. scanf("%d", i);
  4. printf("%d", *i); // Imprime a lo que apunta i
  5.  
  6.  

- Operador &: Devuelve la dirección de una variable. Puedes traducirlo como "la direccion de..."
Código: Text
  1.  
  2. int i;
  3. scanf("%d", &i) // scanf necesita una direccion de memoria
  4.                        // (mira el ejemplo anterior como guía)
  5.  
  6.  

Espero haberte ayudado. Si no he resuelto tu duda ya sabes.

Nos vemos :hola:
Core Dumped
zirrus.es

Ruben3d

  • Miembro HIPER activo
  • ****
  • Mensajes: 710
  • Nacionalidad: es
    • Ver Perfil
    • Web personal
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #2 en: Viernes 6 de Febrero de 2004, 14:33 »
0
Hola.

Citar
Operadores De Indirección (*), De Dirección (&)..., ... y paso por referencia

A CiRRuS le ha faltado explicarte lo de las referencias.

Una referencia es como un puntero que se desreferencia automáticamente y que no puede ser redirigido. Un ejemplo de esto sería:

Código: Text
  1.  
  2. int x = 3;
  3. int& y = x;   // y es una referencia a x
  4. int* z = &x;  // z es un puntero a x
  5.  
  6.  

Aqui declaras una variable x con el valor 3. A continuación declaras una referencia a x, llamada y, cuyo valor es la dirección de memoria de x (fijate que no hay que escribir explicitamente el operador & para obtener la dirección de x, ya que el compilador se da cuenta de que se está inicializando una referencia y lo hace automáticamente). En los ejemplos también pongo un puntero, para que se vea la diferencia. Cuando te quieras referir al 3 puedes hacerlo de dos formas (más la del puntero):

Código: Text
  1.  
  2. cout << "x: " << x << endl;
  3. cout << "y: " << y << endl;
  4.  
  5. // Usando un puntero
  6. cout << "z: " << *z << endl;
  7.  
  8.  

Las tres líneas producirán un 3 por pantalla. Ahora bien, a la hora de modificar el 3 se puede hacer por medio de la referencia, sin tener que desreferenciar con * (como he tenido que hacer con el puntero):

Código: Text
  1.  
  2. x = 4;
  3. cout << "Valor de x: " << x << endl;  // Imprimirá 4
  4. y = 5;
  5. cout << "Valor de x tras cambiarlo a traves de y: " << x << endl;  // Imprimirá 5
  6.  
  7.  

Ahora bien, ¿de qué nos vale esto? La respuesta es el paso de parámetros a funciones. De esta manera podemos pasar objetos a funciones por su dirección de memoria sin tener que realizar una copia de ellos y no teniendo que obligar al programador que use la función a poner explicitamende el operador & :

Código: Text
  1.  
  2. // Función que recibe una referencia
  3. void MiFunc(const int& num)
  4. {
  5.     cout << "He recibido un " << num << endl;
  6. }
  7.  
  8. // Ejemplo de uso
  9. int x = 5;
  10. MiFunc(x);
  11.  
  12.  

La ganancia no queda clara con un int, pero si le pasamos un parámetro que sea un objeto de gran tamaño (imagina una lista de gran tamaño de ojetos complejos)
el ahorro de tiempo y espacio al no tener que hacer el duplicado es considerable.

Esto también puede usarse para modificar el parámetro, si no ponemos el const:

Código: Text
  1.  
  2. // Función que modifica el parámetro
  3. void MiFunc(int& num)
  4. {
  5.     num += 1;
  6. }
  7.  
  8. // Ejemplo de uso
  9. int x = 5;
  10. cout << "x=" << x << endl;  // Imprime "x=5"
  11. MiFunc(x);
  12. cout << "x=" << x << endl;  // Imprime "x=6"
  13.  
  14.  

Espero que con esto te hayan quedado claras las referencias. Tienen más usos, como en sobrecargas de operadores, donde se pueden aprovechar para poder encadenarlos, pero creo que esto es suficiente a modo introductorio.

Un saludo.

Ruben3d


PD: Si he cometido algún error que alguien me avise!

Ruben3d

  • Miembro HIPER activo
  • ****
  • Mensajes: 710
  • Nacionalidad: es
    • Ver Perfil
    • Web personal
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #3 en: Viernes 6 de Febrero de 2004, 14:57 »
0
Meditando, creo que Jordi-18 con "paso por referencia" se refiere al paso por referencia estándar de C y no a las referencias de C++. El post anterior se queda para las generaciones venideras que quieran saber sobre C++ :P

Para pasar un parámetro por referencia (y poder modificarlo) a una función has de pasar su dirección de memoria y, dentro de la función, desreferenciar el puntero para modificarlo. Mira estos ejemplos:

Código: Text
  1.  
  2. // Función desde la que no se puede modificar
  3. void Func1(int num)
  4. {
  5.     num = num + 1;
  6.     printf("Dentro de Func1: %d\n", num);
  7. }
  8.  
  9. // Función que sí modifica
  10. void Func2(int *num)
  11. {
  12.     *num = *num + 1;
  13.     printf("Dentro de Func2: %d\n", *num);
  14. }
  15.  
  16. // Ejemplo de su uso
  17. x = 1;
  18. Func1(x);                                // Desde aqui dentro se imprimirá 2
  19. printf("Tras llamar a Func1: %d\n", x);  // Imprimirá 1
  20. Func2(&x);                               // Desde aqui se imprimirá 2
  21. printf("Tras llamar a Func2: %d\n", x);  // Imprimirá 2
  22.  
  23.  

Espero que con esto te quede claro el paso por referencia.

Un saludo.

Ruben3d

CiRRuS

  • Miembro MUY activo
  • ***
  • Mensajes: 218
    • Ver Perfil
    • http://zirrus.es
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #4 en: Viernes 6 de Febrero de 2004, 16:35 »
0
Okkk Ruben3d, lo de las referencias se me había pasao, de hecho es que nunca lo había usado  :blink: . Me encanta esto de los foros, siempre acabas sabiendo algo más  :D .

Pero creo que lo de las referencias es específico para C++ y lo que explicas del paso de referencias de las funciones. Es válido la declaracion de variables referencia en C?

Nos vemos :hola:
Core Dumped
zirrus.es

Ruben3d

  • Miembro HIPER activo
  • ****
  • Mensajes: 710
  • Nacionalidad: es
    • Ver Perfil
    • Web personal
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #5 en: Viernes 6 de Febrero de 2004, 16:51 »
0
Citar
Es válido la declaracion de variables referencia en C?


No, es específico de C++. Creo que en la pregunta original se refería al paso de parámetros a funciones "por referencia", cosa que ya he explicado un par de post más arriba (debajo del grandote).

Un saludo.

Ruben3d

CiRRuS

  • Miembro MUY activo
  • ***
  • Mensajes: 218
    • Ver Perfil
    • http://zirrus.es
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #6 en: Viernes 6 de Febrero de 2004, 17:38 »
0
Ok, en C no me sonaba eso de variables referencia.

:gracias:

Nos vemos :hola:
Core Dumped
zirrus.es

JoRDi-18

  • Miembro activo
  • **
  • Mensajes: 40
    • Ver Perfil
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #7 en: Lunes 9 de Febrero de 2004, 21:44 »
0
Hola!

Bueno, antes de nada muchísimas gracias a ambos por molestaros en contestar.

Me ha quedado una pequeña duda:

Código: Text
  1.  
  2.  
  3. // Función desde la que no se puede modificar
  4. void Func1(int num)
  5. {
  6.    num = num + 1;
  7.    printf("Dentro de Func1: %d\n", num);
  8. }
  9.  
  10. // Función que sí modifica
  11. void Func2(int *num)
  12. {
  13.    *num = *num + 1;
  14.    printf("Dentro de Func2: %d\n", *num);
  15. }
  16.  
  17. // Ejemplo de su uso
  18. x = 1;
  19. Func1(x);                                // Desde aqui dentro se imprimirá 2
  20. printf("Tras llamar a Func1: %d\n", x);  // Imprimirá 1
  21. Func2(&x);                               // Desde aqui se imprimirá 2
  22. printf("Tras llamar a Func2: %d\n", x);  // Imprimirá 2
  23.  
  24.  
  25.  

Mirando en este ejemplo.

Cuando llamamos a Func2, estamos pasando por referencia un valor que, tras la ejecución de Func2, cambiará su valor.
Mi duda está en la manera de hacer esto... Equivalentemente, ¿se podría hacer esto?

Código: Text
  1.  
  2.  
  3. // Función desde la que no se puede modificar
  4. void Func1(int num)
  5. {
  6.    num = num + 1;
  7.    printf("Dentro de Func1: %d\n", num);
  8. }
  9.  
  10. // Función que sí modifica
  11. void Func2(int *num)
  12. {
  13.    num = num + 1;
  14.    printf("Dentro de Func2: %d\n", *num);
  15. }
  16.  
  17. // Ejemplo de su uso
  18. x = 1;
  19. Func1(x);                                // Desde aqui dentro se imprimirá 2
  20. printf("Tras llamar a Func1: %d\n", x);  // Imprimirá 1
  21. Func2(x);                               // Desde aqui se imprimirá 2
  22. printf("Tras llamar a Func2: %d\n", x);  // Imprimirá 2
  23.  
  24.  
  25.  

Lo que he hecho es modificar
Código: Text
  1.  
  2. Func2(&x);
  3.  
  4.  

y también, dentro de Func2:
Código: Text
  1.  
  2. *num = *num + 1;
  3.  
  4.  


Sólo eso, muchas gracias!
[size=109]Pensamientos elevados deben tener un lenguaje elevado.[/size]
Llamamé Jordi. Cuando me llames así, sonríe.

Ruben3d

  • Miembro HIPER activo
  • ****
  • Mensajes: 710
  • Nacionalidad: es
    • Ver Perfil
    • Web personal
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #8 en: Lunes 9 de Febrero de 2004, 22:41 »
0
Hola.

Ese cambio no funcionará, ya que la declaración de la función indica que hay que pasar un puntero a un entero, no un entero, por lo que hay que obtener su dirección con & . Además, si dentro de la función usas el puntero directamente, sin desreferenciarlo con *, lo que haces es cambiar la dirección de memoria a la que apunta. Por ejemplo, si el puntero vale 0x4DF2 y en esa dirección de memoria hay un int (que es el valor que queremos), al incrementarlo en uno valdrá 0x4DF6 (aumenta 4 bytes, que es el tamaño de un int) y no sabremos a qué está apuntando, por lo que puedes acabar, con suerte, con una violación de segmento y, si no tienes tanta suerte, puede compilar perfectamente, pero modificar el valor de otra variable (imagina para encontrar el fallo).

Espero que esto te lo haya aclarado un poco más.

Un saludo.

Ruben3d

CiRRuS

  • Miembro MUY activo
  • ***
  • Mensajes: 218
    • Ver Perfil
    • http://zirrus.es
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #9 en: Martes 10 de Febrero de 2004, 11:56 »
0
Mmm, violación de segmento... jejejeje, lo siento, pero es cuando oigo esa fraso o Segmentation Fault me entra de todo, escalofrío... pena... risa... jejejeje. Aqui eso se aprende a base de palos  :lol:

Te pega un pedazo segmentation fault de cojones, curiosamente, nunca sem e ha dado el caso de tocar memoria que siga siendo "mia", siempre plas! un segmentation fault.

Nos vemos :hola:
Core Dumped
zirrus.es

ToTeX

  • Nuevo Miembro
  • *
  • Mensajes: 19
    • Ver Perfil
    • http://www.totex.cl
Re: Operadores De Indirección (*), De Dirección (&)...
« Respuesta #10 en: Domingo 22 de Febrero de 2004, 18:26 »
0
Un par de sutilezas puristas:

Es erroneo decir que el 'operador' * se utiliza para declarar punteros: int* pInt;
El * de esta declaracion no tiene nada que ver con el operador de indireccion, es solo una coincidencia de simbolo, el * es solo la sintaxis del lenguaje para declara punteros.

No existe el paso de argumentos por referencia en C, esta caracteristica esta implementada solo en C++. Lo que se hace en C es simular una referencia pasando un objeto(puntero) que representa al dato deseado,  pero el dato en realidad nunca pasa al ambito de la funcion, pasa una copia por valor del puntero.
Salu2... ToTeX
[ www.totex.cl ]