Pasando por referencia en C

Resuelto aks asked hace 14 años • 19 respuestas

Si C no admite pasar una variable por referencia, ¿por qué funciona?

#include <stdio.h>

void f(int *j) {
  (*j)++;
}

int main() {
  int i = 20;
  int *p = &i;
  f(p);
  printf("i = %d\n", i);

  return 0;
}

Producción:

$ gcc -std=c99 test.c
$ a.exe
i = 21 
aks avatar Feb 09 '10 20:02 aks
Aceptado

Porque estás pasando el valor del puntero al método y luego desreferenciandolo para obtener el número entero al que apunta.

tvanfosson avatar Feb 09 '2010 13:02 tvanfosson

Eso no es paso por referencia, es paso por valor como dijeron otros.

El lenguaje C se pasa por valor sin excepción. Pasar un puntero como parámetro no significa pasar por referencia.

La regla es la siguiente:

Una función no puede cambiar el valor real de los parámetros.

(La cita anterior es en realidad del libro K&R)


Intentemos ver las diferencias entre los parámetros escalares y de puntero de una función.

variables escalares

Este breve programa muestra el paso por valor utilizando una variable escalar. paramse llama parámetro formal y variableen la invocación de la función se llama parámetro real. Tenga en cuenta que el incremento paramen la función no cambia variable.

#include <stdio.h>

void function(int param) {
    printf("I've received value %d\n", param);
    param++;
}

int main(void) {
    int variable = 111;

    function(variable);
    printf("variable %d\m", variable);
    return 0;
}

El resultado es

I've received value 111
variable=111

Ilusión de paso por referencia

Cambiamos ligeramente el fragmento de código. parames un puntero ahora.

#include <stdio.h>

void function2(int *param) {
    printf("I've received value %d\n", *param);
    (*param)++;
}

int main(void) {
    int variable = 111;

    function2(&variable);
    printf("variable %d\n", variable);
    return 0;
}

El resultado es

I've received value 111
variable=112

Eso te hace creer que el parámetro fue pasado por referencia. No era. Se pasó por valor, siendo el valor del parámetro una dirección. El valor del tipo int se incrementó, y ese es el efecto secundario que nos hace pensar que fue una llamada a función de paso por referencia.

Punteros: pasados ​​por valor

¿Cómo podemos mostrar/probar ese hecho? Bueno, tal vez podamos probar el primer ejemplo de variables escalares, pero en lugar de escalares usamos direcciones (punteros). Veamos si eso puede ayudar.

#include <stdio.h>

void function2(int *param) {
    printf("address param is pointing to %d\n", param);
    param = NULL;
}

int main(void) {
    int variable = 111;
    int *ptr = &variable;

    function2(ptr);
    printf("address ptr is pointing to %d\n", ptr);
    return 0;
}

El resultado será que las dos direcciones son iguales (no te preocupes por el valor exacto).

Resultado de ejemplo:

address param is pointing to -1846583468
address ptr   is pointing to -1846583468

En mi opinión, esto demuestra claramente que los punteros se pasan por valor. De lo contrario ptrsería NULLdespués de la invocación de la función.

Ely avatar May 29 '2015 01:05 Ely

En C, el paso por referencia se simula pasando la dirección de una variable (un puntero) y eliminando la referencia de esa dirección dentro de la función para leer o escribir la variable real. Esto se denominará "paso por referencia estilo C".

Fuente: www-cs-students.stanford.edu

 avatar Feb 09 '2010 13:02

Porque no hay paso por referencia en el código anterior. El uso de punteros (como void func(int* p)) es pasar por dirección. Esto es paso por referencia en C++ (no funcionará en C):

void func(int& ref) {ref = 4;}

...
int a;
func(a);
// a is 4 now
Alexander Gessler avatar Feb 09 '2010 13:02 Alexander Gessler