Bonjour,
Qui développe ici en 64 bits? plus de problèmes à gérer par rapport à un prog fait en 32 bits?
Avez-vous des conseils ou des liens pour bien débuter dans la prog 64 bits?
Merci pour vos retours![]()
Bonjour,
Qui développe ici en 64 bits? plus de problèmes à gérer par rapport à un prog fait en 32 bits?
Avez-vous des conseils ou des liens pour bien débuter dans la prog 64 bits?
Merci pour vos retours![]()
Ça dépend un peu du modèle 64 bits employé, où les pièges ne sont pas nécessairement les mêmes.
Mais ça tourne toujours autour de la même directive n°1: Ne jamais caster un pointeur en entier d'un autre type que (u)intptr_t ou équivalent.
La plupart des problèmes liés à la programmation 64 bits viennent de là sous Windows.
L'autre règle, c'est utiliser size_t ou ssize_t pour les indices de tableau, plutôt que int ou long.
Et ce, parce que tu peux te retrouver avec des tableaux si grands qu'un int ne suffit plus à en exprimer la taille.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
je vais essayer de comprendre la directive N°1.
Donc, de préférence, développer plus sous Linux que sous Windows?
Non, tu auras des problèmes similaires sous Linux. Windows est correctement documenté et utilise à bon escient intptr_t et équivalents. L'important est simplement de ne pas apprendre la programmation Windows avec un cours obsolète.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Saut,En fait, on peut t'aider sur ce coup là
Ce qu'il faut savoir, c'est qu'un pointeur n'est jamais qu'une valeur numérique entière (généralement non signée) un tout petit peu particulière : elle permet de représenter l'adresse mémoire à laquelle se trouve effectivement l'élément auquel elle fait référence.
Je devrais en fait préciser qu'un pointeur permet de représenter n'importe quelle adresse mémoire accessible au départ du système sur lequel on travaille!.
Du coup, on peut dire que la taille (en nombre de bits) d'un pointeur doit être "au minimum suffisante" pour permettre de représenter toutes les adresses mémoire dont on parle.
En simplifiant à l'extrème (et donc en gardant en mémoire que ce n'est pas forcément le cas partout), on peut estimer que la taille suffisante correspond à 32 bits sur les systèmes 32 bits et qu'elle est de l'ordre de ... 64bits sur les systèmes 64bits.
Au risque de faire une lapalissade, je suis sur que tu te seras rendu compte que le type qui va permettre de représenter une adresse mémoire sur un système 64 bits aura d'office une taille suffisante pour représenter une adresse mémoire 32 bits, mais que l'inverse ne sera pas forcément vrai : il manquera à peu près 32bits à un pointeur de taille suffisante pour représenter une adresse mémoire sur un système 32bits pour qu'il soit en mesure de représenter une adresse mémoire sur un système 64bits.
Ca, c'est ce que l'on peut dire au sujet des pointeurs.
Maintenant, il faut savoir que la norme prévois un certain nombre de types dit "primitifs" permettant de représenter des valeurs numériques: char, short, int, long et long long (pour ne citer que ceux qui permettent de représenter des valeurs entières), que l'on retrouve en version signée et en version non signée.
La différence entre la version signée et la version non signée de chacun de ces type réside dans le fait qu'un des bits permet de représenter le signe - dans la version signée alors qu'il peut être utilisé pour représenter des valeurs supplémentaires dans la version non signée.
En gros, si tu considère un type quelconque, tu te rendra compte qu'il a une taille T de X bits, ce qui permet la représentation de N valeurs différentes.
La version non signée permettra donc de représenter des valeurs comprise dans l'intervalle [0, N[ alors que la version signée permettra de représenter les valeurs comprise dans l'interval [-N/2, N/2[ . Mais ce n'est pas forcément le problème je n'en ai parlé que pour être complet)
Le gros problème, c'est que la norme laisse le choix de la taille des types primitifs à l'implémentation.
Tout ce qu'elle dit, c'est que le type char a d'office la taille 1 et que les autres types ont d'office une taille qui est un multiple de la taille d'un char selon les règles suivantesPartant de là, il ne faut pas être grand clerc pour se rendre compte que le type qui aura "une taille suffisante" pour représenter "n'importe quelle adresse" sur un système donné peut parfaitement correspondre à... n'importe lequel des types non signés fournis par la norme.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 sizeof(char) == 1 sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) sizeof(unsigned char) <= sizeof(unsigned short) <= sizeof(unsigned long) <= sizeof(unsigned long long) sizeof(char) == sizeof(unsigned char)
Sur deux systèmes 32 bits différents, cela pourrait très bien correspondre au type unsigned int de l'un et au type unsigned long de l'autre!
Et si l'on s'intéresse aux systèmes 64bits, cela pourrait très bien correspondre au type unsigned int d'un premier système qu'au type unsigned long d'un deuxième ou au type unsigned long long d'un troisième
Le gros problème est donc que, si tu te dis que "bah, la taille d'un pointeur correspond au type unsigned int de mon système", ce ne sera vrai que pour ton système particulier et que, sur un autre système, un pointeur risque de se retrouver très à l'étroit s'il doit rentrer dans un unsigned int, ce qui occasionnera la perte de toute une partie de l'information qui permet d'identifier l'adresse mémoire
Par chance, la norme a prévu le problème et demande aux différentes implémentation de prévoir un typedef nommé intptr_t (et / ou une version non signée uintptr_t) qui corresponde au type "de taille suffisante pour représenter n'importe quelle adresse mémoire".
Ce typedef pourrait parfaitement correspondre à un typedef sur le type (unsgined) int d'un système qu'à un typedef sur le type (unsigned)long d'un autre ou à un typedef sur le type (unsigned) long long d'un troisième, mais nous, en tant que développeur, on n'en a plus rien à faire : c'est pris en compte par la "magie" du compilateur, et, tout ce qu'il nous reste à faire, c'est à utiliser le type (u)intptr_t lorsqu'on veut représenter la valeur numérique correspondant à l'adresse mémoire à laquelle se trouve un objet.
La deuxième règle est basée exactement sur le même principe mais s'intéresse à la valeur que l'on peut donner à l'indice d'un tableau plutôt que de s'intéresser à la valeur que l'on peut donner à une adresse mémoire![]()
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Partager