Parece que las respuestas anteriores no tienen contexto y no abordan la propiedad de que los punteros C están sobrecargados. Es completamente justo afirmar que C "pasa por referencia". Un puntero es una referencia, también. Sin embargo, más formalmente, una "referencia" C es el mecanismo para representar la dirección de memoria de un símbolo.
- Un puntero es simplemente una variable en la memoria cuyo valor se trata como una dirección .
- Una referencia es simplemente el valor literal de una dirección de memoria.
- El lenguaje C permite pasar por referencia, ¡pero solo en el contexto correcto!
La separación del contexto es la definición de la firma y la invocación de la firma.
Considere las primitivas int a = 0x22e8;
y en otro lugar declaramos int* b = &a;
(accederé a las funciones en un minuto).
Podríamos visualizar esto en memoria (se supone endianness no importa para este ejemplo):
...
0x00000200: 22e8 ; this is the variable for int a's literal value:
; a == 0x000022e8
; &a == 0x00000200
0x00000???: 9090 ; ... more code ...
0x00000400: 0200 ; this is pointer b pointing to a's address:
; b == 0x00000200
; *b == 0x000022e8
; &b == 0x00000400
...
Es fácil ver que podemos asignar un puntero a cualquier dirección sin ningún truco especial. Un puntero es solo una variable, pero C nos permite hacer referencia a la dirección a la que apunta; podemos "quitar la referencia" del puntero de su dirección de valor para tratar en cambio el puntero como el valor subyacente de su ponente durante un contexto de invocación: while (*b == a) ...
. Podríamos invocar fácilmente b == &a
.
Al aplicar esto a las llamadas a funciones, debe separar el contexto de la definición de función (firma) frente a la invocación para diferenciar el pase por referencia.
int* foo(int* blah, int nah) { .. } // signature definition context:
// These are parameters
... vs ...
b = foo(&a, 4); // invocation context:
// These are arguments
En la definición de una firma de función, que no están diciendo al compilador que se refieren a un argumento se accede desde — el tiempo de ejecución ni siquiera sabe todavía! No tiene sentido definir void bar(int &blah) {...}
. En su lugar, utilizamos la sintaxis del puntero desreferenciado — "cualquier argumento que se pase se cargará en la dirección apuntada a" — para hacer referencia al valor del argumento deseado cuando se produce el tiempo de ejecución. Por lo tanto, C puede pasar argumentos por referencia.
Los contextos de las definiciones de firmas de funciones y de las llamadas a funciones cambian la forma en que el compilador examina la sobrecarga del puntero frente a la referencia, y cómo el tiempo de ejecución realmente puede abordarlos.
¿Por qué crees que pasar por referencia debería funcionar en C?C no tiene pase por referencia. –
Claro que sí. Simplemente llama a sus referencias "punteros". – Crashworks
"punteros" no son "pasar por referencia". Pase lo que pase a una función en C, se pasa por valor. Puede suceder que lo que se pasa sea un puntero, en cuyo caso, la función recibe una * copia del puntero *, y puede usar esa copia para cambiar el valor apuntado por el puntero, pero el puntero se pasa por valor . –