Il y a un moment dans l'étude du langage C, où on a l'impression que les
tableaux et les pointeurs sont plus ou moins interchangeables, en un mot
que c'est pratiquement la même chose.
il faut donc être très clair :
un tableau et un pointeur ce n'est pas la même chose.
Quand on déclare, ailleurs qu'en paramètre formel de fonction,
int t[10];
on déclare un tableau, et le compilateur réserve une zone de 10 entiers
consécutifs.
Quand on déclare int *p, il s'agit toujours d'un pointeur, et le
compilateur réserve simplement un élément de mémoire pouvant contenir un
pointeur.
Les caractéristiques du langage C qui créent la confusion dans l'esprit des
utilisateurs, sont les trois règles suivantes :
1.
tout identificateur de type tableau de X apparaissant dans
une expression est converti en une valeur constante de type pointeur vers
X, et ayant comme valeur l'adresse du premier élément du tableau ;
2.
un paramètre formel de fonction, de type tableau de X est considéré
comme étant de type pointeur vers X ;
3.
la sémantique de l'opérateur d'indexation est la suivante : T[i]
est équivalent à *(T + i).
Le point important à comprendre dans la règle 2 est que tableau de
X est la même chose que pointeur vers X uniquement dans le
cas de paramètre formel de fonction.
Donc void fonc (int t[]) { ... } est équivalent à void fonc (int * t) { ... }.
Les types des objets déclarés de type tableau ou de type pointeur
sont différents dans tous les autres
contextes, que ce soit déclaration de variables globales ou locales à une
fonction.
Différence entre règle 1 et règle 2 : une déclaration int t[10]
qui n'est pas un paramètre formel, déclare un tableau de 10 entiers.
Ce sont les utilisations ultérieures de t qui subissent une conversion
en type pointeur vers entier.
Par contre, à la déclaration d'un paramètre formel int t[],
c'est la déclaration elle-même qui est transformée en int *t.
Les chaînes littérales viennent ajouter à la confusion, car on peut
déclarer char t[] = "Hello"; et char *p = "Hello";.
Dans le premier cas, le compilateur alloue un tableau de 6 caractères qu'il
initialise avec les caractères H, e, l, l, o et \0.
Toute occurrence de t dans une expression sera convertie en type
pointeur vers char.
Dans le second cas, le compilateur alloue un tableau de 6 caractères qu'il
initialise de la même manière que dans le premier cas, mais de surcroît,
il alloue une variable de type pointeur vers char qu'il initialise
avec l'adresse du premier caractère de la chaîne.
char t[] = "Hello";
char *p = "Hello";
Ceci est un cas particulier des tableaux de caractères qui ne se reproduit pas
avec les autres types.
On peut déclarer un tableau d'entiers par int t[] = {1, 2, 3, 4, 5};,
mais on ne peut pas déclarer un pointeur vers un tableau d'entiers par :
int *p = {1, 2, 3, 4, 5};.