Se connecter avec
S'enregistrer | Connectez-vous

Souci de pointeu

Dernière réponse : dans Programmation

Salut tout le monde,

Je cherche de l'aide pour comprendre la différence entre :
ceci : int *t = new int[3]

et ceci: int **p = new int*[3];

La première expression crée un tableau dont le pointeur t retiendra l'adresse de départ.
Mais que fait la deuxième. Je n'arrive pas a résoudre un exercice de compréhension de code à cause de cette petite ligne qui me bloque littéralement.

merci d'avance!

A priori c'est du c++ vu que c'est ce que je suis sensé étudier..

Autres pages sur : souci pointeu

Lassé par la pub ? Créez un compte

Meilleure solution

Expert Programmation

Es-tu vraiment sûr d'avoir tout compris.
Je parie que tu n'as pas pigé la ligne 8 :

p est un int**, c'est-à-dire un pointeur de pointeur d'entier.
p[] est un élément de int**, c'est donc un int*, un pointeur d'entier.
On ne peut donc pas faire de soustraction avec. Sauf à considérer qu'un pointeur, c'est une adresse représentable comme un entier. Comme faire accepter au compilateur un changement de type ? Il suffit de caster (transtyper) la variable. Pour transtyper une variable, on met le type voulu devant :
int p[]
Pour préciser que ce n'est pas seulement p mais p[] qui est à transtyper, on ajoute des parenthèses de priorité :
int(p[])
Si le type voulu s'écrit en plusieurs mots, on ajouter aussi des parenthèses, comme à la ligne 22 :
p = (int**)( t);
Ici les parenthèses autour de t sont inutiles et alourdissent le code :
p = (int**)t;


C'est pourtant facile le C++ :sol: 



edit: Just grilled by Batchy ;) 
Expert Programmation

il faut voir les étoiles comme des couches :

un int* pointe vers un int
un int** pointe vers un int*
un int*** pointe vers un int**
ect ...

dans le cas des tableaux c'est la même chose, juste qu'on pointe vers le premier élément. comme ton premier élément est un int*, alors il te faut un int** pour pointer dessus.

Yeah merci!!! C'est juste trop clair maintenant!
Vraiment sympa de m'avoir aidé, j'ai compris quelque chose!
Je vais peut être abuser mais je bloque sur la fin de ce code:
Je dois trouver ce qu'il affiche mais le corrigé n'est pas clair..
C'est que j'ai un exam mercredi et j'aimerais bien éviter de laisser des énormes failles..
Au passage, je veux bien un petit topos sur les conversions avec cette tronche : (int**)( t); enfin de toute facon ça fait parti du morceau de code qui me fait m'arracher les cheveux!

  1. int *t = new int[3];
  2. int **p = new int*[3];
  3. for (int i=0; i<3; i++) {
  4. p[i] = t + i; t[i] = 10 + i;
  5. }
  6. cout << "1. " << *p[1] << endl;
  7.  
  8. cout << "2. " << int(p[2]) - int(p[1]) << endl;
  9.  
  10. for (int i=0; i<3; i++)
  11. t[i] = (t + i) - *(p + i);
  12. // jusque la j'ai compris: on obtient :1. 11
  13. //et 2. 4
  14.  
  15. cout << "2. " << t[1] << endl;
  16. // et 2. 0 ici.
  17.  
  18. for (int i=0; i<3; i++)
  19. t[i] = i;
  20.  
  21. t[0] = int(p); // la c'est la misère!
  22. p = (int**)( t);
  23.  
  24. t = (int *) t[0];
  25. cout << "3. " << int(p[2]) << endl;
  26. cout << "4. " << *p[2] << endl;
  27.  
  28. // mais a la fin le code est censé afficher:
  29. //3. 2
  30. //Segmentation fault


/* Si c'est pas trop demander, j'aimerais bien que quelqu'un m'explique à partir du "la c'est la misère!"
J'espère que c'est plus ou moins lisible, j'ai essayé d'aérer le code au max..*\
Expert Programmation

reiden57, bonjour et bienvenu. Va lire le règlement, mets ton message correctement en forme en le modifiant (et non pas en réécrivant tout). Merci. Ecoute les bons conseils de Naf-Naf/Storos, sa maison est en brique mais il n'aime pas voir le loup sortir du bois pour autant. :D 
Expert Programmation

reiden57 a dit :
  1. int *t = new int[3];
  2. int **p = new int*[3];
  3. for (int i=0; i<3; i++)
  4. t[i] = i;
  5.  
  6. t[0] = int(p); // la c'est la misère!
  7. p = (int**)( t);
  8. t = (int *) t[0];
Caster un pointeur vers un entier
est de toute façon indéfini. Si tu est en 64bit mais que tes entiers font toujours 32bit, ça va foirer. Je me demande pourquoi ton prof fait ça. C'est peut être pour ajouter des difficultés, mais en pratique, tu ne code jamais ça, hein ? ;) 
Supposont qu'on soit en 32bit et que le cast se passe bien (ce qui est déjà une grosse hypothese)
t[0] contient donc, en tant qu'entier, le contenu de p, c'est à dire l'adresse du tableau de int*.
Ensuite, t, qui est un pointeur int* vers le tableau d'entiers int[3],
est mis dans p. C'est à dire que le tableau d'entier int[3] va être traité comme un tableau d'entier int*[3]
donc le t[0] de tout à l'heure, si on le lit comme p[0], il ne sera plus traité comme un entier mais comme un pointeur vers un entier. (même si au départ, c'est un int**)
Ensuite on met t[0] dans t. Si on regarde bien deux lignes plus haut, le t[0] correspond à (int**)p (l'ancien p, le vrai).
Si on regarde bien, en gros on à échangé la valeur de t et la valeur de p,
en s'affranchissant des types. Il y a juste la valeur de t[0] qui à changé, est qui est égale au nouveau t (ou à l'ancien p)

reiden57 a dit :
  1. cout << "3. " << int(p[2]) << endl;
  2. cout << "4. " << *p[2] << endl;

p[2] est égal à l'ancien t[2], c'est à dire, euh ... 2, sauf que le 2 est pris comme un pointeur, donc c'est une adresse 2.

Ensuite, on essaye d'aller à l'adresse 2. À priori, on ne sait pas ce qu'il y a, donc on peut vraisemblablement dire que ça plante.

(juste comme ça, dans des distributions de linux pas si vielles que ça, il était possible de mettre effectivement des données à l'adresse 2 en utilisant la fonction mmap(), mais cela entraînait une faille de sécurité, donc les dernières version l'interdisent (quand elles peuvent).)
Expert Programmation

:) 

Non, les topics ne se ferment pas ici. Par contre, tu peux élire la meilleure réponse. Le topic sera alors marqué comme résolu, mais nous pourrons toujours y ajouter des commentaires.
Lassé par la pub ? Créez un compte