Páginas

24 de jun. de 2011

Paso por valor y por referencia en C

No tengo intención de escribir tantas entradas en un mismo día, pero bueno acabo de empezar y las ganas de escribir me corroen.


En este caso más que escribir voy a pegar, ya dije que hablaría de más cosas y no solo de Debian o Linux en general. Esta vez voy a hablar del lenguaje de programación C. En un foro resolví una duda que tenía un compañero sobre la diferencia entre el paso por valor y el paso por referencia de los argumentos a una función así que voy a aprovechar (ya que para algo lo he escrito yo) y voy a hacer un copy&paste aquí.

Cuando una función contiene unos parámetros, estos, pueden pasarse a la función de dos formas: por valor y/o por referencia.

Cuando nosotros llamamos a una función, esta guarda sus variables en la RAM y al terminar de ejecutarse la función, todos los datos y variables que se cargaron en memoria se borran ya que no van a volver a ser utilizadas. 

Voy a poner un ejemplo fácil de una función que realiza la suma de dos números y devuelve el resultado de dicha suma:

CÓDIGO: 
int suma (int a, int b)
{
    int resultado;
    
    resultado = a + b;
    
    return resultado;
}

En el main para llamar a la función simplemente la llamaríamos pasándole a la función las variables a y b:


CÓDIGO:
int main ()
{
    int a=10, b=15, var;
    
    var = suma(a, b);
    
    return 0;
}

Ahí la variable "var" va a valer lo que devuelva la función suma (como le pasamos 10 y 15, var valdría 25).

Como he dicho la función suma reserva espacio en memoria para sus variables locales. En el ejemplo serían a, b y resultado. 

Como veis en la función main he llamado a la función suma pasándole a y b. Pero estas variables a y b de main NO son las mismas variables a y b de la función suma. Son una copia que están almacenadas en otra dirección de memoria. Es decir cuando llamamos a la función tendríamos dos variables "a" y otras dos variables "b" con el mismo valor en diferentes posiciones de memoria.

Si modificamos el valor de 'a' en la función suma, no cambia el valor de 'a' en la función principal puesto que son copias, no son la misma.

Esto es lo que sería el paso por valor. Ahora voy a intentar explicar el paso por referencia.

Ya os imaginaréis cual es la gracia del paso por referencia, que es ni más ni menos, que al llamar a la función no le pasemos una copia, si no que le pasemos la variable original en sí. Para ello lo que hacemos es pasarle la dirección de memoria de dicha variable, al pasarle su dirección estamos trabajando directamente sobre ella, por lo que cualquier cambio que hagamos en la función a esa variable también se verá cambiado en el main.

Voy a utilizar el mismo ejemplo de la suma:

CÓDIGO: 
void suma (int a, int b, int *resultado)
{
    *resultado = a + b;
}

La función suma la he cambiado a tipo void, antes la puse tipo int para que devolviera el valor de un entero con el resultado de la suma. Ahora no hace falta, simplemente le paso las variables que necesito. 

Las variables "a" y "b" las he vuelto a pasar como antes, por valor, ya que no las voy a modificar para nada. En cambio ahora he creado una variable de tipo int, que es un puntero, que es donde voy a guardar el resultado. Como he dicho antes, el paso por referencia consiste en pasarle la dirección de memoria de la variable a la función y sabemos que lo que trabaja con direcciones son los punteros.

La función main quedaría así:


CÓDIGO: 
int main ()
{
    int a=10, b=15, resultado=0;
    
    suma(a, b, &resultado);
    
    printf("%d", resultado);
    
    return 0;
}

Creamos nuestras variables igual que siempre, llamamos a la función y le pasamos la variable "a" y "b" por valor. La variable "resultado" es la que va a ser modificada en la función ya que almacenará el valor de la suma, para pasarlo por referencia necesitamos su dirección de memoria, por eso he puesto el "&" delante (recuerdo que el & delante del nombre de una variable nos da la dirección de memoria en la que se encuentra dicha variable).

Como podréis comprobar la función suma ahora es de tipo void y no devuelve nada, el cambio se queda reflejado en la variable que hemos pasado por referencia, ya que al no ser una copia sino que directamente trabajamos sobre dicha variable, vemos cuanto vale el valor de la suma en la función principal.
Y eso es todo, espero que os sirva a alguno de ayuda y si tenéis alguna duda o corrección de lo que escribo no dudéis en usar los comentarios para ello.

2 comentarios:

  1. Muchísimas gracias. Lo has explicado de una forma muy sencilla. Me está siendo muy útil. Gracias, gracias, gracias.

    ResponderEliminar
  2. buenisimo brother .... mas adelante tendre algunas preguntillas de programas en C amigo...

    ResponderEliminar