Hay un patrón cuando se trata de matrices y funciones; Es un poco difícil de ver al principio.
Cuando se trata de matrices, es útil recordar lo siguiente: cuando una expresión de matriz aparece en la mayoría de los contextos, el tipo de la expresión se convierte implícitamente de "matriz de elementos N de T" a "puntero a T", y su valor se establece para apuntar al primer elemento en la matriz. Las excepciones a esta regla son cuando la expresión de matriz aparece como un operando ya sea del &o de sizeoflos operadores, o cuando se trata de una cadena literal de ser utilizado como un inicializador en una declaración.
Por lo tanto, cuando llama a una función con una expresión de matriz como argumento, la función recibirá un puntero, no una matriz:
int arr[10];
...
foo(arr);
...
void foo(int *arr) { ... }
Es por eso que no utiliza el &operador para argumentos correspondientes a "% s" en scanf():
char str[STRING_LENGTH];
...
scanf("%s", str);
Debido a la conversión implícita, scanf()recibe un char *valor que apunta al comienzo de la strmatriz. Esto es válido para cualquier función llamada con una expresión de matriz como argumento (casi cualquiera de las str*funciones *scanfy *printffunciones, etc.).
En la práctica, probablemente nunca invocará una función con una expresión de matriz utilizando el &operador, como en:
int arr[N];
...
foo(&arr);
void foo(int (*p)[N]) {...}
Tal código no es muy común; debe conocer el tamaño de la matriz en la declaración de la función, y la función solo funciona con punteros a matrices de tamaños específicos (un puntero a una matriz de 10 elementos de T es un tipo diferente que un puntero a una matriz de 11 elementos de T).
Cuando una expresión de matriz aparece como un operando para el &operador, el tipo de la expresión resultante es "puntero a la matriz de elementos N de T", o T (*)[N], que es diferente de una matriz de punteros ( T *[N]) y un puntero al tipo base ( T *)
Cuando se trata de funciones y punteros, la regla a recordar es: si desea cambiar el valor de un argumento y hacer que se refleje en el código de llamada, debe pasar un puntero a lo que desea modificar. Una vez más, las matrices arrojan un poco de una llave inglesa en las obras, pero primero nos ocuparemos de los casos normales.
Recuerde que C pasa todos los argumentos de función por valor; el parámetro formal recibe una copia del valor en el parámetro real, y cualquier cambio en el parámetro formal no se refleja en el parámetro real. El ejemplo común es una función de intercambio:
void swap(int x, int y) { int tmp = x; x = y; y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(a, b);
printf("after swap: a = %d, b = %d\n", a, b);
Obtendrá el siguiente resultado:
antes del intercambio: a = 1, b = 2
después del intercambio: a = 1, b = 2
Los parámetros formales xy yson objetos distintos de ay b, por lo que cambia xy yno se refleja en ay b. Como queremos modificar los valores de ay b, debemos pasarles punteros a la función de intercambio:
void swap(int *x, int *y) {int tmp = *x; *x = *y; *y = tmp; }
...
int a = 1, b = 2;
printf("before swap: a = %d, b = %d\n", a, b);
swap(&a, &b);
printf("after swap: a = %d, b = %d\n", a, b);
Ahora su salida será
antes del intercambio: a = 1, b = 2
después del intercambio: a = 2, b = 1
Tenga en cuenta que, en la función de intercambio, no cambiamos los valores de xy y, sino los valores de what xy y point to . Escribir en *xes diferente de escribir en x; no estamos actualizando el valor en xsí mismo, obtenemos una ubicación xy lo actualizamos en esa ubicación.
Esto es igualmente cierto si queremos modificar un valor de puntero; si escribimos
int myFopen(FILE *stream) {stream = fopen("myfile.dat", "r"); }
...
FILE *in;
myFopen(in);
entonces estamos modificando el valor del parámetro de entrada stream, no lo que stream apunta , por lo que cambiar streamno tiene efecto sobre el valor de in; Para que esto funcione, debemos pasar un puntero al puntero:
int myFopen(FILE **stream) {*stream = fopen("myFile.dat", "r"); }
...
FILE *in;
myFopen(&in);
Una vez más, las matrices arrojan un poco de una llave inglesa en las obras. Cuando pasa una expresión de matriz a una función, lo que recibe la función es un puntero. Debido a cómo se define la suscripción de matriz, puede usar un operador de subíndice en un puntero de la misma manera que puede usarlo en una matriz:
int arr[N];
init(arr, N);
...
void init(int *arr, int N) {size_t i; for (i = 0; i < N; i++) arr[i] = i*i;}
Tenga en cuenta que los objetos de matriz pueden no asignarse; es decir, no puedes hacer algo como
int a[10], b[10];
...
a = b;
por lo tanto, debe tener cuidado cuando trabaje con punteros a matrices; algo como
void (int (*foo)[N])
{
...
*foo = ...;
}
no funciona