Una duda sobre punteros (es básico eh)

Colapsar
X
 
  • Tiempo
  • Mostrar
Limpiar Todo
nuevos mensajes
  • CosmicBoy
    sorrounded
    • 15-12-2006
    • 1444

    #1

    Una duda sobre punteros (es básico eh)

    Tengo una duda en el siguiente ejercicio:

    #include <stdio.h>

    int suma( int *a, int b )
    {
    int c;

    c = *a + b;
    *a = 0;
    return c;
    }

    int main()
    {
    int var1, var2, resultado;

    var1 = 5; var2 = 8;
    resultado = suma(&var1, var2);
    printf( "La suma es: %i y a vale: %i\n", resultado , var1 );
    }
    El ejercicio no tiene gran utilidad, es solamente para aprender.
    La duda la tengo sobre el valor que marqué con negrita, ¿por qué se le agrega antes el símbolo "&" (que sirve para pasar la direccion de la variable)?

    Yo sé, por pura practica que si no se le agrega el "&" en la pantalla no se imprime a "var1" con valor 0, que es el valor que adquiere luego de ejecutarse la funcion suma, sino que se lo imprime con valor 5.

    En resumen, no me cierra por qué, teoricamente, se debe usar en este caso particular el símbolo "&"

    alguien que me ayude plis

    Gracias desde ya a los que quieran ayudar, toy arrancando con esto de programar y me estoy enganchando bastante tambien


     

    karate + fútbol... no la mejor combinación
  • Piluex
    Away
    • 10-10-2004
    • 3038

    #2
    Como dijiste cuando colocas el signo & pasas la direccion en memoria de la variable y no su valor. Y en la funcion se toma esa variable como un puntero a un int. Entonces ese puntero se "llena" con la direccion de la variable que vos pases y trabaja directamente con la variable. Entonces vas a poder modificar su valor desde la funcion a diferencia de la segunda variable que se pasa por valor, aunque vos en la funcion coloques "b=0" no va amodificar el valor de var2, a diferencia que al modificar "*a" modificas directamente var1.

    * adelante de una expresion se utiliza para indicar que deseamos trabajar con la direccion a la que apunta y no con la direccion (un simple numero) en si. Record&#225;, el puntero es simplemente una direccion de memoria. Obvio q tenes que entender bien, que todas tus variables son "porciones" de memoria interpretadas seg&#250;n el tipo de variable que les asignes. Que ejercicio mas aburrido para aprender punteros. Es OBVIO q asi no van a llegar a ning&#250;n lado, no hay mucho para jugar.


    Creo q no dije nada mal, estoy en la oficina desde las 8 am. Saludos.
    Editado por última vez por Piluex; 16-01-2007, 01:08 AM.

    Comentario

    • CosmicBoy
      sorrounded
      • 15-12-2006
      • 1444

      #3
      Gracias che, no me quedo del todo claro pero me ayuda a sacarlo un toque

      Es OBVIO q asi no van a llegar a ning&#250;n lado, no hay mucho para jugar.
      Por algo se empieza... por lo menos los meros mortales tenemos que aprender de a poco


       

      karate + fútbol... no la mejor combinación

      Comentario

      • CosmicBoy
        sorrounded
        • 15-12-2006
        • 1444

        #4
        Entend&#237; todo en realidad, pasa que de la forma en que yo entiendo el codigo, el signo "&" est&#225; de m&#225;s, y quiero entender la forma en que se DEBE entender el c&#243;digo...


         

        karate + fútbol... no la mejor combinación

        Comentario

        • judío ginger daywalker petiso
          Pelotudo
          • 14-03-2005
          • 16758

          #5
          es asi:

          una variable del tipo "int *" es un puntero al tipo int. esto significa que la variable va a almacenar una direccion de memoria.

          tecnicamente hablando, tanto un "int *" como un "char *" como un "long double *" guardan lo mismo en memoria: un entero de 32 bits (o 64 en micros de 64 bits, y 16 en micros de 16 bits) que almacena una direccion en la RAM.

          entonces, supongamos que tenemos una variable del tipo "int *" llamada "myptr". C te permite operar tanto sobre la variable puntero propiamente dicha (es decir, sobre la variable "int *", que almacena un entero de 32 bits que representa una direccion de memoria) o sobre el valor de la variable (cuyo tipo se asume entero, ya que el puntero es un puntero a entero) a la cual apunta.

          si yo hago asignaciones directamente sobre "myptr", estoy en el 1er caso: estoy cambiando el valor que representa la direccion de memoria a acceder.
          si hiciera, por ejemplo "myptr = 100;", le estoy diciendo "hace que myptr apunte a la direccion de memoria 100. y hacer luego "*myptr" va a devolver el valor del entero apuntado. en este caso, esto seria "agarra desde la posicion 100 de la memoria, consideralo un int (32 bits), y devolve el valor que tendria si en efecto ese pedazo de memoria guardara un int".

          entonces, uno facilmente se da cuenta que si quiere usar un puntero como puntero, es necesario tener a mano direcciones de memorias "utiles", y no ese 100 que yo acabo de sacar de la galera... y como conseguimos direcciones de memoria utiles, como por ejemplo la direccion donde esta guardada otra variable (direccion que, dicho sea de paso, cambia cada vez que el proceso se ejecuta)? usando el operador "&". este operador unario se antecede a las variables y significa "la direccion en memoria de la variable que sigue".
          si yo miro el valor de, por ejemplo, "&myptr", lo que vamos a obtener es la direccion en memoria donde esta almacenado el entero de 32 bits que almacena la direccion de memoria a la cual apunta *myptr!
          si tengo un "int a = 5;", "&a" nos va a devolver la direccion de memoria donde esta almacenada esa variable. es solo un numero, por ejemplo "901796".

          combinando esto con lo anterior, vemos que podemos hacer que *myptr represente el valor de un entero almacenado en cualquier lado de la memoria, siempre y cuando sepamos donde queremos mirar. ahora que sabemos que "&a" nos da la direccion en memoria de "a", podemos ver que hacer "myptr = &a" almacena en myptr una direccion de memoria, que es la misma donde esta almacenado "a". luego, hacer "*myptr" nos devuelve el valor del entero en esa posicion, que es el "5" que habiamos asignado originalmente.
          y hacer "*myptr = 2" asigna 2 en el entero que esta en la direccion almacenada en myptr, por lo que si ahora miramos el valor de "a", este va a ser 2.

          suele ser buena practica no mezclar los tipos de punteros, pero tambien suele ser util hacerlo. aca hay que recordar algo: cuando uno tiene una direccion de memoria y quiere leer el valor alli guardado, tiene que saber QUE es ese valor, por una cuestion simple: la direccion es un punto de inicio, pero tengo que saber el final, y como esta organizada la data en esos bits consecutivos de memoria. ahi es donde entra en juego el tipo de datos del puntero, y es lo que diferencia un "int *" de un "char *". en el primer caso, cuando hago "*myptr", al ser un "INT *", el compilador sabe que eso significa "mirar los 4 bytes empezando dde el apuntado por myptr"; y en el segundo sabe que "*mycharptr" significa "mirar 1 byte empezando dde el apuntado por mycharptr". tambien esto afecta la llamada "aritmetica de punteros".
          hacer myptr++ (sin el asterisco) hace que *myptr apunte al proximo entero en memoria. es decir, le suma a la direccion almacenada en myptr el tama&#241;o en bytes del tipo de datos apuntado. en el caso de enteros, 4.
          es decir que si tengo "int * myptr = 100;", hacer "myptr++" deja "myptr" valiendo 104.
          y en el caso de "char * mycharptr = 100;", hacer "mycharptr++" deja "mycharptr" en 101.

          por ultimo, cuando se toma una direccion con &, esa direccion tambien es un entero de 32 (o 64, o 16) bits, y es indistinguible una "direccion de un entero" de una "direccion de un char" de una "direccion de un long double". los tipos aca solo importan para una cosa: para que el compilador te putee.

          si hago "int * myptr; char mychar; myptr = & mychar;", aunque tecnicamente es realizable, te van a putear suponiendo que te confundiste. simplemente castealo a mano ("myptr = (int *)&mychar;"), y a lo tuyo...

          finalmente, el absurdo:
          suponete que no pones el &, como segun vos deberia ser...
          que terminas haciendo? terminas asignandole a un puntero a entero una direccion inventada. ya que estas usando como direccion el valor almacenado en la variable var1, que es "5". por lo que de ahi en adelante "*a" apunta al entero almacenado en la direccion "5". ni bien intentes usar ese valor, deberia morirse el proceso y tirarte un SEGMENTATION FAULT (*nix) o GENERAL PROTECTION ERROR (windows 9x) o simplemente una ventanita de error en nt/2k/xp.

          K
          Editado por última vez por judío ginger daywalker petiso; 17-01-2007, 12:02 AM.

          Comentario

          • Piluex
            Away
            • 10-10-2004
            • 3038

            #6
            gracias kkkkkk x explicarlo bien Piluex no esta en condiciones de explicar cosas jauajauaj.

            Comentario

            • CosmicBoy
              sorrounded
              • 15-12-2006
              • 1444

              #7
              che excelente lo tuyo kkkkkk

              Muchas Gracias

              PD: Piluex tambien fue grande lo tuyo =P no lo digo por chupamedias pero esta bueno conseguir respuestas siendo un noob


               

              karate + fútbol... no la mejor combinación

              Comentario

              • CosmicBoy
                sorrounded
                • 15-12-2006
                • 1444

                #8
                Ah, y sin el signo "&" no me manda fruta el compilador eh, solamente que var1 no se vuelve cero... pero no hay ningun SEGMENTATION FAULT ni GENERAL PROTECTION ERROR ni SI NO ME CHUPAS LA PIJA NO SIGO ni nada de eso


                 

                karate + fútbol... no la mejor combinación

                Comentario

                • Cadarlion
                  Tecnohippie
                  • 09-03-2004
                  • 12908

                  #9
                  ah, que desilucion no vi que estaba en programacion, pense que hablaban de Punteros

                  Si Hoc Legere Scis Nimium Eruditionis Habes

                  Comentario

                  • Sir_Binario
                    Egelito activo
                    • 26-01-2006
                    • 492

                    #10
                    Originalmente publicado por Cadarlion
                    ah, que desilucion no vi que estaba en programacion, pense que hablaban de Punteros

                    yo tambien, venia a pedir direcciones...

                    Comentario

                    • MoaLaiSkirulais
                      ^^(V)^^
                      • 08-07-2003
                      • 23268

                      #11
                      tomen ahi tienen varias, de nada....

                      Comentario

                      • Cadarlion
                        Tecnohippie
                        • 09-03-2004
                        • 12908

                        #12
                        Originalmente publicado por MILITO
                        jajajajajajajaj!

                        Vende barato? vende de calidad?

                        Si Hoc Legere Scis Nimium Eruditionis Habes

                        Comentario

                        • judío ginger daywalker petiso
                          Pelotudo
                          • 14-03-2005
                          • 16758

                          #13
                          no te tira error porque tu sistema operativo apesta y no esta controlando que leas o escribas en memoria ajena tu proceso...
                          digamos:
                          "c = *a + b;" aca lees memoria direccionada "a mano". si te salis de la memoria de tu proceso, linux te mata el programa. windows nt/2k/xp deberia matartelo tambien. windows 9x no te dice nada, DOS tampoco.
                          "*a = 0;" aca escribis en esa memoria. nuevamente, si no es tuya, linux te mata el programa. windows nt/2k/xp casi seguro que tambien. si no te lo matan, entonces existe la probabilidad de que se te tilde el sistema y te salte una BSOD. en windows 9x/dos o no pasa nada pq tubiste suerte, o se te tira BSOD...

                          en fin, por esa mentalidad ("si no salta nada entonces no hay bug") la mayoria de los programadores terminan muriendose en sus propios bugs cuando pasan a linux...

                          K
                          Editado por última vez por judío ginger daywalker petiso; 18-01-2007, 03:39 PM.

                          Comentario

                          • Nagual Bones
                            Son of the Bard
                            • 14-04-2003
                            • 21698

                            #14
                            Originalmente publicado por Cadarlion
                            jajajajajajajaj!

                            Vende barato? vende de calidad?


                            jauajua



                            coso, tnx kkkkkk por la explicacion, tenia siempre esa duda con los punteros pero toda la paja para buscarlo.


                            El camino del nagual...

                            You become what you believe.

                            Comentario

                            • judío ginger daywalker petiso
                              Pelotudo
                              • 14-03-2005
                              • 16758

                              #15
                              wens, ya que esto termino, vengo a offtopiquear con fotos de BSODs...





                              K

                              Comentario

                              Trabajando...