J'avais pas pensé a poser la question avant mais, j'ai remarqué qu'on préfère toujours les expression du typequeCode:*(tableau+index)
c'est pas la même chose?Code:tableau[index]
Version imprimable
J'avais pas pensé a poser la question avant mais, j'ai remarqué qu'on préfère toujours les expression du typequeCode:*(tableau+index)
c'est pas la même chose?Code:tableau[index]
Perso, je préfère l'expression avec les braquets...
Mais cela revient en effet à la même chose:
D'un coté, avec les braquets, tu dis "je veux l'élément à l'indice index", et de l'autre, tu dis "je veux ce qui se trouve à l'adresse (début du tableau+(index*taille de l'élément) ) "
Et comme, l'indice index correspond à l'adresse du début du tableau + (index * taille de l'élément)...
Maintenant, il faut savoir qu'il y a quelques situations dans lesquelles l'un est préférable à l'autre (mais sans fournir l'index, alors)...
Tous les conteneurs de la STL qui ne fournissent pas un accès aléatoire aux éléments (donc, en gros, tous à l'exception de std::vector) et qui forcent l'utilisation d'un iterateur nécessitent le recours à (*iterateur) pour accéder au contenu.
On peut donc estimer que l'utilisation de la syntaxe *(tableau +index) assure une meilleure homogénéité d'écriture... Mais c'est un avis que je ne partage pas forcément ;)
Si t[i] = *(t+i) pourquoi ce message alors?
Bizarre j'ai toujours cru que *(t+i) était plus rapide?
*************************************************
@NiamorH : Non on incrémente pas le pointeur on fait l'addition avec "lon". Mais bon c'est tellement illisible :mouarf: (en plus d'être sûrement moins rapide vu qu'on fait un cast a chaque fois. Donc je garde ta solution)
Il n'y a que peu de raisons que ce soit le cas, à défaut de pouvoir certifier qu'il n'y en a aucune :D
Mes essais persos montrent qu'un code simple dans lequel le seul changement est la tranfsormation d'un acces en tab[i] en un acces en *(tab+i) produit exactement le même code assembleur, sous réserve, évidemment, d'utiliser les même options d'optimisation.
Et, dans l'ensemble, ce n'est pas *si* étonnant que cela: le jeu d'instruction reste malgré tout (relativement :question:) limité, même si on demande explicitement d'utiliser le jeu des processeurs les plus récents :roll:
Il est donc *relativement* logique que deux codes suivant exactement la même logique générale pour mener à un résultat identique fourniront une succession d'instructions processeurs identique ;)...
Maintenant, comprenons nous bien: je me base ici sur mes observations personnelles en utilisant mon compilateur (gcc 4.2.1 en l'occurrence).
Il n'est pas impossible que de "vieux" compilateurs (et donc moins "techniquement au point") ou que d'autres compilateurs puissent avoir des résultat différents. Et c'est la principale raison de l'"extrême prudence" de mes propos ;) :P
Merci :ccool:
Je tiens a signaler quand même que Mr. Bruce Eckel, malgré son formidable travail a bien joué son coup, avec quelque fois des exercices sans grandes indications et où on ne voit même pas le but recherché, il arrive a bloqué le lecteur désireux de connaître la solution (souvent bête), avec juste en dessus le petit message subliminalJe peux vous dire que si j'avais une MasterCard y a bien longtemps que j'aurai craqué :aie:Citation:
Solutions to selected exercises can be found in the electronic document The Thinking in C++ Annotated Solution Guide, available for a small fee from http://www.BruceEckel.com.
exemple d'exercices le n°1 du chapitre 4 :Et il ne donne même pas la déclaration de puts, comme si c'était évident qu'elle retourne un int (et si vous mettez void a la place ou quelque chose d'autre ça ne marchera pas). Et pire encore il ne dit même que c'est avec le compilateur c que ça doit marcher. Il abandonne complètement son lecteur.Citation:
# In the Standard C library, the function puts( ) prints a char array to the console (so you can say puts("hello")). Write a C program that uses puts( ) but does not include <stdio.h> or otherwise declare the function. Compile this program with your C compiler. (Some C++ compilers are not distinct from their C compilers; in this case you may need to discover a command-line flag that forces a C compilation.) Now compile it with the C++ compiler and note the difference.
ou encore cette exercice complètement inutile :sans commentaire :roll:Citation:
(Challenging) Modify FloatingAsBinary.cpp so that it prints out each part of the double as a separate group of bits. You’ll have to replace the calls to printBinary( ) with your own specialized code (which you can derive from printBinary( )) in order to do this, and you’ll also have to look up and understand the floating-point format along with the byte ordering for your compiler (this is the challenging part).
Au mieux ça t'apprend a Googler mais ça te fais perdre du temps :P
Je me console en me disant que la pauvreté et la meilleur école. :(
Ah oui exact.
Alors le static_cast est fait à la compilation, normalement il n'y a aucune perte de rapidité significative à l'éxécution. dynamic_cast est le seul cast où il y a perte de perfs.
Par contre tu fais une addition et moi une simple incrémentation.
Peut-on parler d'une simple incrémentation pour un pointeur vers un entier?
En fait, une incrémentation ne peut que difficilement être autre chose que "simple"...
Sémantiquement parlant, le terme incrémentation signifie "ajouter 1 à la valeur de"...
Cela signifie que, si tu as une variable numérique qui vaut 4 et que tu l'incrémente, elle ne peut pas valoir autre chose que... 5 :roll:
La seule nuance au niveau des pointeurs est que le fait de les incrémenter fournit l'adresse à laquelle l'élément suivant du type géré par le pointeur *devrait* théoriquement se trouver.
Tu as raison, durant la compil, un static_cast génère un peu de code, mais très optimisé, notamment des affectations qui, si elles sont effectuées sur des objets, peuvent entraîner l'appel du constructeur par copie. Sur les types de base ça reste très léger, peut-être plus lourd quand même que la différence entre addition et incrémentation, je ne sais pas.
Bonjour tout le monde,
Attention le poste risque d'être un peu longuet je m'en excuse.
Je suis à l'exo 22 du chapitre 4.
N.B : Stash = sorte de tableau dynamique. Stack = Pile ( ;) )
Exo terminé mais y a quelque chose qui me gêne, c'est que si je décide de supprimer les chaîne allouée dynamiquement avec delete je rencontre une très longue erreur à l'executionCitation:
Créez un Stack qui contient des Stashes. Chaque Stash contiendra 5 lignes d'un fichier passé en entrée. Créez les Stashes en utilisant new. Chargez le contenu d'un fichier dans votre Stack, puis réaffichez-le dans sa forme origninale en extrayant les données de la structure Stack.
et dès que je commente le delete tout marche au poile.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 *** glibc detected *** ./exo22: free(): invalid pointer: 0xb7e2a164 *** ======= Backtrace: ========= /lib/tls/i686/cmov/libc.so.6[0xb7d4cd65] /lib/tls/i686/cmov/libc.so.6(cfree+0x90)[0xb7d50800] /usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7f15d81] /usr/lib/libstdc++.so.6(_ZNSs4_Rep10_M_destroyERKSaIcE+0x1d)[0xb7ef190d] /usr/lib/libstdc++.so.6(_ZNSsD1Ev+0x51)[0xb7ef37b1] ./exo22[0x8048ec4] /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7cf9050] ./exo22(__gxx_personality_v0+0x41)[0x8048a61] ======= Memory map: ======== 08048000-0804a000 r-xp 00000000 16:43 2310435 /home/riad/Programmation/cpp/testString/exo22 0804a000-0804b000 rw-p 00001000 16:43 2310435 /home/riad/Programmation/cpp/testString/exo22 0804b000-0806c000 rw-p 0804b000 00:00 0 [heap] b7b00000-b7b21000 rw-p b7b00000 00:00 0 b7b21000-b7c00000 ---p b7b21000 00:00 0 b7ce2000-b7ce3000 rw-p b7ce2000 00:00 0 b7ce3000-b7e27000 r-xp 00000000 16:42 621387 /lib/tls/i686/cmov/libc-2.6.1.so b7e27000-b7e28000 r--p 00143000 16:42 621387 /lib/tls/i686/cmov/libc-2.6.1.so b7e28000-b7e2a000 rw-p 00144000 16:42 621387 /lib/tls/i686/cmov/libc-2.6.1.so b7e2a000-b7e2d000 rw-p b7e2a000 00:00 0 b7e2d000-b7e37000 r-xp 00000000 16:42 457878 /lib/libgcc_s.so.1 b7e37000-b7e38000 rw-p 0000a000 16:42 457878 /lib/libgcc_s.so.1 b7e38000-b7e39000 rw-p b7e38000 00:00 0 b7e39000-b7e5c000 r-xp 00000000 16:42 621391 /lib/tls/i686/cmov/libm-2.6.1.so b7e5c000-b7e5e000 rw-p 00023000 16:42 621391 /lib/tls/i686/cmov/libm-2.6.1.so b7e5e000-b7f46000 r-xp 00000000 16:42 1766046 /usr/lib/libstdc++.so.6.0.9 b7f46000-b7f49000 r--p 000e8000 16:42 1766046 /usr/lib/libstdc++.so.6.0.9 b7f49000-b7f4b000 rw-p 000eb000 16:42 1766046 /usr/lib/libstdc++.so.6.0.9 b7f4b000-b7f51000 rw-p b7f4b000 00:00 0 b7f64000-b7f67000 rw-p b7f64000 00:00 0 b7f67000-b7f81000 r-xp 00000000 16:42 1520740 /lib/ld-2.6.1.so b7f81000-b7f83000 rw-p 00019000 16:42 1520740 /lib/ld-2.6.1.so bff96000-bffac000 rw-p bff96000 00:00 0 [stack] ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso] Abandon (core dumped)
Dont j'ai cerné le problème (j'ai supprimer la pile) et la il s'agit juste d'utiliser le stash pour copier les lignes une à une. puis de les afficher et j'ai le même problème. Je pose la solution du problème simplifié :
Voila c'est vraiment pas compliqué. Ca se passe au niveau de "delete ligne" (avant dernière). si je libère pas les string tout marche bien, sinon ça foire.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 int main(int argc, char* argv[]) { ifstream in("main.cpp"); Stash tabDyn; tabDyn.initialize(sizeof(string*)); //Fichier->Stash string line; while(getline(in, line)) tabDyn.add(new string(line)); //Affichage du fichier string *ligne; for(int i = 0; i < tabDyn.count(); i++) { ligne = (string*) tabDyn.fetch(i); cout << *ligne << endl; delete ligne; } tabDyn.cleanup();; }
Il faut savoir que Stash à été écrite et présentée par l'auteur lors du chapitre 4. Si vous voulez que je poste ici le Stash.cpp et Stash.h y a pas de problème.
Si vous trouvez le message trop long où voulez plus de précisions n'hésitez pas.
Théoriquement la désallocation, c'est ton tableau qui la fait, donc je ne vois pas trop ce qui se passe du tout :koi:
@miles : On voulant te répondre, j'ai revu la fonction add de la class Stash, et j'ai enfin compris mon erreur et compris ce qui s'est passé, je m'explique :
1- La classe Stash n'est qu'un tableau de char, dont on spécifie la taille du type qu'elle est sensé stocker a l'initialisation. Et la fonction addprend donc un pointeur vers l'élément qu'on veut ajouter. Or moi qui voulais stocké un pointeur vers un string je n'envoyais qu'un...pointeur vers un string alors qu'il fallait envoyer un pointeur vers un pointeur de string. Même chose pour la valeur a retourner. Donc la version corrigée :Code:int Stash::add(const void* element)
Donc pour répondre a miles, non tabDyn.cleanup() ne fais pas tout, car, et ça tu ne pouvais pas le savoir :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 void main(int argc, char* argv[]) { ifstream in("main.cpp"); Stash tabDyn; tabDyn.initialize(sizeof(string*)); //Fichier->Stash string line; while(getline(in, line)) { string *tempLine = new string(line); tabDyn.add(&tempLine); } //Affichage du fichier string *ligne; for(int i = 0; i < tabDyn.count(); i++) { ligne = *((string**) tabDyn.fetch(i)); cout << *ligne << endl; delete ligne; } tabDyn.cleanup();; }
Elle ne fais que supprimer le tableau de char qui stockait les éléments.Code:
1
2
3
4
5
6 void Stash::cleanup() { if(storage != 0) { //cout << "freeing storage" << endl; delete []storage; } } ///:~
Maintenant que c'était il passé avant, et bien tout simplement en envoyant un pointeur vers un string, l'élément copié dans le tableau était le string, qui, et je viens de le remarquer ne tient que sur 4 octet et qui est donc un genre de référence vers la vrai structure stockée quelque part dans la mémoire. Donc j'avais apparement la même valeur que maintenant suaf que le delete ne marchais pas avant vu qu'on ne supprimé pas avant un vrai pointeur (en tout cas pas déclaré en tant que tel).
Je sais pas si vous comprenez :lol:
Si je me suis trompé n'hésitez pas.
En tout cas Merci miles.
J'ai pas tout saisi, mais si tu as une erreur de moins, tant mieux :)