Quando si programma in C (o C ++) ci sono tre modi diversi per specificare il parametro in una funzione che accetta una matrice.
Ecco un esempio (implementando std::accumulate
da C ++ in C) che mostra cosa intendo.
Posso scrivere in questo modo:
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
Questo può anche essere scritto su questo (che significa la stessa cosa):
int accumulate(int n, int array[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
Posso anche scrivere in questo modo:
int accumulate(int n, int (*array)[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += (*array)[i];
}
return sum;
}
Tutte queste opzioni sono molto simili e generano lo stesso codice eseguibile ma hanno una leggera differenza, ovvero il modo in cui il chiamante passa gli argomenti.
Ecco come vengono richiamate le prime due opzioni:
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), a));
return 0;
}
Ecco come viene chiamata l'opzione thrid:
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
return 0;
}
Si noti che la terza opzione richiede all'utente di specificare esplicitamente l'indirizzo di a
con &a
. Le prime due opzioni non richiedono questo perché gli array vengono convertiti implicitamente in puntatori dello stesso tipo in C.
Ho sempre preferito il terzo approccio.
Ecco perché:
-
È più coerente con il modo in cui altri tipi vengono passati dai puntatori.
int draw_point(struct point *p); int main() { struct point p = {3, 4}; draw_point(&p); // Here is the 'address of' operator required. }
-
Rende possibile utilizzare macro come
ARRAY_LENGTH
per ottenere la quantità di elementi nella matrice.#include <stdio.h> #define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0])) void this_works(int (*array)[10]) { /* This works! */ printf("%d\n", ARRAY_LENGTH(*array)); } void this_is_invalid_and_dangerous(int array[10]) { /* This does NOT work because 'array' is actually a pointer. */ printf("%d\n", ARRAY_LENGTH(array)); }
L'unico vantaggio che vedo con int array[]
(e int *array
) è che puoi scrivere array[X]
invece di (*array)[X]
quando vuoi prendere un indice.
Quali sono i tuoi pensieri professionali su questo? Quale approccio pensi sia migliore e perché? Hai mai mescolato i due? Se sì, quando scegli cosa?
Come ho detto, ho sempre preferito usare int (*array)[N]
, ma vedo che anche gli altri due approcci sono abbastanza comuni.