Comme vous venez d'apprendre C, je vous recommande d'essayer vraiment de comprendre les différences entre les tableaux et les pointeurs d'abord plutôt que les choses courantes .
Dans le domaine des paramètres et des tableaux, il existe quelques règles déroutantes qui devraient être claires avant de continuer. Tout d'abord, ce que vous déclarez dans une liste de paramètres est traité de manière spéciale. Il y a de telles situations où les choses n'ont pas de sens en tant que paramètre de fonction en C. Ce sont
- Fonctions comme paramètres
- Tableaux en tant que paramètres
Tableaux en tant que paramètres
Le second n'est peut-être pas immédiatement clair. Mais cela devient clair quand on considère que la taille d'une dimension de tableau fait partie du type en C (et un tableau dont la taille de dimension n'est pas donnée a un type incomplet). Donc, si vous créez une fonction qui prend un tableau par valeur (reçoit une copie), alors elle ne peut le faire que pour une taille! De plus, les tableaux peuvent devenir volumineux et C essaie d'être aussi rapide que possible.
En C, pour ces raisons, les valeurs de tableau n'existent pas. Si vous souhaitez obtenir la valeur d'un tableau, vous obtenez à la place un pointeur vers le premier élément de ce tableau. Et c'est là que réside déjà la solution. Au lieu de dessiner un paramètre de tableau invalide à l'avance, un compilateur C transformera le type du paramètre respectif en un pointeur. Rappelez-vous ceci, c'est très important. Le paramètre ne sera pas un tableau, mais plutôt un pointeur vers le type d'élément respectif.
Maintenant, si vous essayez de passer un tableau, ce qui est passé à la place est un pointeur vers le premier élément des tableaux.
Excursion: fonctionne comme paramètres
Pour terminer, et parce que je pense que cela vous aidera à mieux comprendre la question, regardons quel est l'état des choses lorsque vous essayez d'avoir une fonction comme paramètre. En effet, d'abord cela n'aura aucun sens. Comment un paramètre peut-il être une fonction? Huh, nous voulons une variable à cet endroit, bien sûr! Donc, ce que fait le compilateur lorsque cela se produit, c'est encore une fois de transformer la fonction en un pointeur de fonction . Essayer de passer une fonction passera un pointeur vers cette fonction respective à la place. Ainsi, les éléments suivants sont identiques (analogues à l'exemple de tableau):
void f(void g(void));
void f(void (*g)(void));
Notez que les parenthèses autour *g
sont nécessaires. Sinon, il spécifierait une fonction retournant void*
, au lieu d'un pointeur vers une fonction retournant void
.
Retour aux tableaux
Maintenant, j'ai dit au début que les tableaux peuvent avoir un type incomplet - ce qui arrive si vous ne donnez pas encore de taille. Puisque nous avons déjà compris qu'un paramètre de tableau n'existe pas mais qu'à la place tout paramètre de tableau est un pointeur, la taille du tableau n'a pas d'importance. Cela signifie que le compilateur traduira tous les éléments suivants, et tous sont la même chose:
int main(int c, char **argv);
int main(int c, char *argv[]);
int main(int c, char *argv[1]);
int main(int c, char *argv[42]);
Bien sûr, cela n'a pas beaucoup de sens de pouvoir y mettre n'importe quelle taille, et c'est juste jeté. Pour cette raison, C99 a proposé une nouvelle signification pour ces nombres et permet à d'autres choses d'apparaître entre les crochets:
// says: argv is a non-null pointer pointing to at least 5 char*'s
// allows CPU to pre-load some memory.
int main(int c, char *argv[static 5]);
// says: argv is a constant pointer pointing to a char*
int main(int c, char *argv[const]);
// says the same as the previous one
int main(int c, char ** const argv);
Les deux dernières lignes indiquent que vous ne pourrez pas changer "argv" dans la fonction - c'est devenu un pointeur const. Cependant, seuls quelques compilateurs C prennent en charge ces fonctionnalités C99. Mais ces caractéristiques montrent clairement que le «tableau» n'en est pas un. C'est un indicateur.
Un mot d'avertissement
Notez que tout ce que j'ai dit ci-dessus n'est vrai que lorsque vous avez un tableau en tant que paramètre d'une fonction. Si vous travaillez avec des tableaux locaux, un tableau ne sera pas un pointeur. Il se comportera comme un pointeur, car comme expliqué précédemment, un tableau sera converti en pointeur lors de la lecture de sa valeur. Mais il ne doit pas être confondu avec des pointeurs.
Un exemple classique est le suivant:
char c[10];
char **c = &c; // does not work.
typedef char array[10];
array *pc = &c; // *does* work.
// same without typedef. Parens needed, because [...] has
// higher precedence than '*'. Analogous to the function example above.
char (*array)[10] = &c;