Le traitement des tableaux par C est très différent de celui de Java et vous devrez ajuster votre réflexion en conséquence. Les tableaux en C ne sont pas des objets de première classe (c'est-à-dire qu'une expression de tableau ne conserve pas son "tableau" dans la plupart des contextes). En C, une expression de type "tableau à N éléments de T
" sera implicitement convertie ("décroissance") en une expression de type "pointeur vers T
", sauf lorsque l'expression de tableau est un opérande des opérateurs ou des opérateurs sizeof
unaires &
, ou si le expression de tableau est une chaîne littérale utilisée pour initialiser un autre tableau dans une déclaration.
Entre autres choses, cela signifie que vous ne pouvez pas passer une expression de tableau à une fonction et la recevoir en tant que type de tableau ; la fonction reçoit en fait un type de pointeur:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
Dans l'appel à foo
, l'expression str
est convertie du type char [6]
à char *
, c'est pourquoi le premier paramètre de foo
est déclaré à la char *a
place de char a[6]
. Dans sizeof str
, puisque l'expression de tableau est un opérande de l' sizeof
opérateur, elle n'est pas convertie en type pointeur, vous obtenez donc le nombre d'octets dans le tableau (6).
Si vous êtes vraiment intéressé, vous pouvez lire The Development of the C Language de Dennis Ritchie pour comprendre d'où vient ce traitement.
Le résultat est que les fonctions ne peuvent pas renvoyer de types de tableau, ce qui est bien puisque les expressions de tableau ne peuvent pas non plus être la cible d'une affectation.
La méthode la plus sûre consiste pour l'appelant à définir le tableau et à transmettre son adresse et sa taille à la fonction qui est censée y écrire:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
Une autre méthode consiste pour la fonction à allouer le tableau dynamiquement et à renvoyer le pointeur et la taille:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
Dans ce cas, l'appelant est responsable de la désallocation du tableau avec la free
fonction de bibliothèque.
Notez que dst
dans le code ci-dessus se trouve un simple pointeur vers char
, pas un pointeur vers un tableau de char
. La sémantique du pointeur et du tableau de C est telle que vous pouvez appliquer l'opérateur indice []
à une expression de type tableau ou de type pointeur; les deux src[i]
et dst[i]
accèdera au i
'ième élément du tableau (même s'il src
n'a qu'un type de tableau).
Vous pouvez déclarer un pointeur vers un tableau à N éléments T
et faire quelque chose de similaire:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
Plusieurs inconvénients avec ce qui précède. Tout d'abord, les anciennes versions de C s'attendent SOME_SIZE
à être une constante de compilation, ce qui signifie que cette fonction ne fonctionnera qu'avec une seule taille de tableau. Deuxièmement, vous devez déréférencer le pointeur avant d'appliquer l'indice, ce qui encombre le code. Les pointeurs vers des tableaux fonctionnent mieux lorsque vous avez affaire à des tableaux multidimensionnels.