Pointeur à pointeur avec argv

Basé sur ma compréhension du pointeur à pointeur vers un tableau de caractères,

% ./pointer one two argv +----+ +----+ | . | ---> | . | ---> "./pointer\0" +----+ +----+ | . | ---> "one\0" +----+ | . | ---> "two\0" +----+ 

À partir du code:

 int main(int argc, char **argv) { printf("Value of argv[1]: %s", argv[1]); } 

Ma question est la suivante: Pourquoi argv [1] est-il acceptable? Pourquoi n’est-ce pas quelque chose comme (* argv) [1]?

Ma compréhension comprend les étapes suivantes:

  1. Prenez argv, déréférence.
  2. Il devrait renvoyer l’adresse du tableau de pointeurs aux caractères.
  3. Utilisation de l’arithmétique de pointeur pour accéder aux éléments du tableau.

Il est plus pratique de considérer [] comme un opérateur pour les pointeurs plutôt que pour les tableaux; il est utilisé avec les deux, mais depuis que les tableaux se désintègrent, l’indexation de tableaux a toujours du sens si elle est considérée de cette façon. Donc, essentiellement, cela compense, puis déréférence, un pointeur.

Donc avec argv[1] , ce que vous avez vraiment est *(argv + 1) exprimé avec une syntaxe plus pratique. Cela vous donne le deuxième caractère char * dans le bloc de mémoire pointé par argv , puisque caractère char * correspond au type pointé par argv , et que [1] décale argv par sizeof(char *) octets puis déréférence le résultat.

(*argv)[1] déréférencer argv premier avec * pour obtenir le premier pointeur sur char , puis compenser par 1 * sizeof(char) octets, puis en supprimant la référence pour obtenir un caractère. Cela donne le deuxième caractère de la première chaîne du groupe de chaînes pointé par argv , ce qui n’est évidemment pas la même chose que argv[1] .

Pensez donc à une variable de tableau indexé comme à un pointeur opéré par un opérateur “décalage puis déréférencement d’un pointeur”.

Puisque argv est un pointeur sur pointeur sur caractère, il en résulte que argv[1] est un pointeur sur caractère. Le format print() %s attend un pointeur sur l’argument char et imprime le tableau de caractères terminé par un caractère null auquel pointe l’argument. Puisque argv[1] n’est pas un pointeur nul, il n’y a pas de problème.

(*argv)[1] est également valide C, mais (*argv) est équivalent à argv[0] et est un pointeur sur char , donc (*argv)[1] est le deuxième caractère de argv[0] , qui est / dans votre exemple.

L’indexation d’un pointeur en tant que tableau la supprime implicitement. p[0] est *p , p[1] est *(p + 1) , etc.