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 :)
Version imprimable
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.
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.
Saut,En fait, on peut t'aider sur ce coup là :D
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:
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 :aie:
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 :aie:
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 ;)