En C, todos los argumentos de función se pasan por valor; cualquier cambio en el parámetro formal de la función no se refleja en el parámetro real.Por ejemplo:
void foo(int bar)
{
bar = bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(x);
printf("x after foo = %d\n", x);
return 0;
}
La salida del programa será
x before foo = 0
x after foo = 0
porque bar
recibe el valor de x
(0), no una referencia a x
sí mismo. Cambiar bar
no tiene ningún efecto en x
.
En C, la forma de evitar esto es para pasar un punteroa una variable:
void foo(int *bar)
{
*bar = *bar + 1;
}
int main(void)
{
int x = 0;
printf("x before foo = %d\n", x);
foo(&x);
printf("x after foo = %d\n", x);
return 0;
}
Ahora, la salida del programa es
x before foo = 0
x after foo = 1
Esta vez, el parámetro formal bar
no es un int, sino un puntero a int, y recibe la dirección de x
(dada por expresión &x
en la llamada al foo
), no el valor contenido en x. La expresión *bar
significa "obtener el valor en la barra de ubicación puntos a", por lo que *bar = *bar + 1
corresponde a x = x + 1
.
Dado que scanf()
necesita escribir en sus argumentos, espera que esos argumentos se escriban como punteros. El especificador de conversión "% d" espera que el argumento correspondiente sea un puntero a int (int *
), el especificador de conversión "% u" espera un puntero a unsigned int (unsigned *
), "% s" espera un puntero a char (char *
) , "% f" espera que un puntero flote (float *
), etc. En su ejemplo, dado que a
se escribe int
, debe usar la expresión &a
para obtener un puntero.
Tenga en cuenta que si a
eran ya un tipo de puntero, no sería necesario utilizar el operador &
en la llamada a scanf()
:
int main(void)
{
int a, *pa; // declare pa as a pointer to int
...
pa = &a; // assign address of a to pa
scanf("%d", pa); // scanf() will write to a through pa
...
}
Tenga en cuenta también que al pasar una matriz a una función (por ejemplo, cuando utilizando el especificador de conversión "% s" para leer una cadena), no necesita usar el operador &
; la expresión de matriz implícitamente puede convertir en un tipo de puntero:
int main(void)
{
char name[20];
...
scanf("%19s", name); // name implicitly converted from "char [20]" to "char *"
...
}
Como un aparte, 'main' devuelve' int', no 'void'. –