2010-03-15 5 views
3

j'ai demandé il y a quelque temps sur un compte que je ne me souviens pas comment manipuler des pointeurs de base et quelqu'un m'a donné une très bonne démoaide de base nécessaire avec des pointeurs (double indirection)

par exemple

char *ptr = "hello" (hello = a char array) 

si maintenant * ptr pointe du doigt h

ptr++ = déplace le PTR pour pointer sur l'élément suivant, pour obtenir sa valeur que je fais * ptr et qui me donne un e

ok jusqu'ici j'espère: D mais maintenant je dois manipuler un char **ptr et me demandais comment je fais cela d'une manière qui mimmicks les effets d'un tableau 2d?

quelques conseils de base seraient très appréciés car je dois faire une tâche qui a un **ptr pour imiter un tableau 2d et sans savoir comment il fait ce premier moyen, je ne peux même pas le résoudre sur le papier (par exemple, comment pouvez-vous déréférencer un ** ptr, comment obtenez-vous des valeurs [x] [y], etc.)

remercie

Répondre

4

un pointeur vers un pointeur est juste que. Par exemple:

// Declare our double-indirection pointer. 
char** ptr; 
// And initialize it: 
char s1[] = "hello"; 
char s2[] = "world"; 
ptr = malloc(sizeof(char*) * 2); 
ptr[0] = s1; 
ptr[1] = s2; 
// ptr now points to a pointer that points to 'h'. 
char* ptr2 = *ptr; 
// ptr2 points to 'h'. 
char* ptr3 = *(ptr + 1); 
// ptr3 points to "w". 
char c = **ptr; // could be written as *(*ptr) 
// c = 'h'. 
char c2 = *(*(ptr + 1)); 
// c2 = 'w'. 
char c3 = *(*(ptr) + 1); 
// c3 = 'e'. 
+0

gcc lève les avertissements de wome sur cette première ligne (initialisation à partir du type de pointeur incompatible, éléments en excès dans l'initialiseur scalaire). Vous utilisez un initialiseur de tableau sur un type non-tableau. –

+0

Vous avez raison. Edité dans un correctif. –

1

Vous pouvez les utiliser comme un tableau bidimensionnel normal. (Depuis effectivement, c'est ce qu'ils sont)

char** ptr = {"lorem", "ipsum", "dolor"}; 
char* s1 = ptr[0]; //Points to the beginning of "lorem" 
char* s2 = ptr[1]; //Points to the beginning of "ipsum" 
char c = ptr[2][4]; //Contains 'r' 

Cela est dû au fait que:

int *a; 
//... 
int i = a[6]; 
int j = *(a + 6); //Same as previous line! 

Cheers,

Amit Ron--

8

Vous pouvez indicer un pointeur de la même manière que vous pouvez inscrire un tableau, à condition que toutes les adresses aient été correctement configurées.

En supposant la déclaration suivante:

char **ptr; 

ici sont les types des différentes expressions:

 
     Expression  Type  Equivalent expressions (yield same value)  
     ----------  ----  ----------------------------------------- 
       ptr  char ** &ptr[0] 
      *ptr  char * ptr[0] 
     *(ptr+i)  char * ptr[i]; &ptr[i][0] 
      **ptr  char  ptr[0][0] 
     *(*(ptr+i))  char  ptr[i][0]; *ptr[i] 
    *(*(ptr+i)+j)  char  ptr[i][j] 

ainsi:

  • ptr peuvent être traitées comme si était un tableau de chaînes (tableau 2-d de char)
  • ptr[i] points au début de la chaîne i'th dans la liste
  • ptr[i][j] est la valeur du caractère de la chaîne j-ième i'th dans la liste
  • Les expressions ptr++ et ++ptr avancera ptr pour pointer vers la prochaine chaîne
  • les expressions (*ptr)++ et ++(*ptr) avancera *ptr pour pointer vers le caractère suivant

en ce qui concerne la mise en place yo Pour les pointeurs, cet agencement suppose que tout a déjà été alloué sous la forme de tableaux statiques ou dynamiquement via malloc. Vous ne pouvez simplement écrire

char **ptr = {"foo", "bar", "bletch"}; // using aggregate initializer on 
             // non-aggregate type; bad juju, 
             // a.k.a undefined behavior 

ou

char **ptr;   // ptr has not been initialized to point anywhere 
ptr[0] = "foo";  // dereferencing ptr via subscript invokes undefined 
ptr[1] = "bar";  // behavior 
ptr[2] = "bletch"; 

En général, lorsque vous utilisez un pointeur comme si elle était un tableau, vous utiliserez malloc ou quelque chose de similaire à répartir vos tampons:

char **ptr = malloc(sizeof *ptr * N); 
if (ptr) 
{ 
    ptr[0] = "foo"; // ptr[i] gets address of 
    ptr[1] = "bar"; // string literal 
    ptr[2] = "bletch"; 
    ... 
} 

ou

char **ptr = malloc(sizeof *ptr * N); 
if (ptr) 
{ 
    size_t i; 
    for (i = 0; i < N; i++) 
    { 
    ptr[i] = malloc(sizeof *ptr[i] * M); // strictly speaking, the sizeof 
    if (ptr[i])       // is not necessary here 
    { 
     //initialize ptr[i] 
    } 
    } 
} 
+0

+1, cependant "' ptr' et 'ptr [0]' tous les deux pointent vers le début de la première chaîne de la liste "est incorrect. Contrairement au cas des tableaux 2D (qui sont contigus pour toutes leurs dimensions), 'ptr' ne pointe pas au même endroit que' ptr [0] '. –

+0

Pour faire votre premier exemple de travail: 'char * ary [] = {" foo "," bar "," bletch "}; char ** ptr = & ary [0]; 'Ceci déclarerait' ptr' comme un "pointer-to-array" et puisque chaque élément du tableau est une chaîne (qui est lui-même un tableau), 'ptr' est par essence un" pointer-to-array-of-array ". Soyez prudent lorsque vous faites un double déréférencement avec ce type de pointeur 'char **'; Puisque les chaînes n'ont pas la même longueur, vous devrez vous assurer que vous effectuez toutes les vérifications de limites nécessaires. – bta

+0

@Max - vous avez raison (avait des tableaux sur le cerveau pour une raison quelconque). J'ai enlevé cette déclaration. Merci pour la capture. –