2011-10-03 4 views
18

Sur la base de ma compréhension du pointeur sur pointeur sur un tableau de caractères,pointeur vers pointeur avec argv

% ./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, pourquoi est-argv [1] acceptable? Pourquoi n'est-ce pas quelque chose comme (* argv) [1]?

Mes étapes de compréhension:

  1. Prenez argv, déréférencer.
  2. Il doit retourner l'adresse du tableau de pointeurs aux caractères.
  3. Utilisation de l'arithmétique du pointeur pour accéder aux éléments de la matrice.
+3

+1 pour le diagramme. :) – Mysticial

Répondre

14

Il est plus commode de penser à [] comme opérateur pour les pointeurs plutôt que des tableaux; il est utilisé avec les deux, mais depuis la désintégration des tableaux en pointeurs, l'indexation des tableaux a toujours du sens si elle est regardée de cette façon. Donc essentiellement cela compense, puis déréférences, 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 char * dans le bloc de mémoire pointé par argv, puisque char * est le type argv points, et offsets argv par sizeof(char *) octets puis déréférence le résultat.

(*argv)[1] aurait déréférencer argv d'abord avec * pour obtenir le premier pointeur vers char, puis compenser que par 1 * sizeof(char) octets, déréférence alors que pour obtenir un char. 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 tableau indexée comme un pointeur qui est opéré par un opérateur "offset puis déréférencer un pointeur".

+0

Oui, j'ai eu la confusion de pourquoi nous n'avions pas besoin de derefrence argv, d'abord mais il s'avère que j'ai oublié qu'il est égal à * (argv + n), où n est l'indice indice. –

10

Parce que argv est un pointeur vers pointeur vers char, il en résulte que argv[1] est un pointeur vers char. Le format print()%s attend un pointeur vers l'argument char et imprime le tableau de caractères à terminaison nulle vers lequel pointe l'argument. Puisque argv[1] n'est pas un pointeur nul, il n'y a pas de problème.

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

4

L'indexation d'un pointeur sous forme de tableau le supprime implicitement. p[0] est *p, p[1] est *(p + 1), etc.

Questions connexes