Pour faire de l'arithmétique de pointeurs, l'utilisation de char * au lieu de void * peut en effet nécessiter davantage de casts. Cependant, c'est comme ça qu'on fait en C standard. Ici, tu ne te soucies pas de portabilité entre les principaux compilos existants, mais dans le cas général, cette extension non standard casse la compatibilité avec certains des principaux compilos. Membre de la TI-Chess Team. Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP. |
La solution en réalité c'est la réponse D: ça ne marche pas. Un void* n'a pas de type et donc de taille unitaire. Mais je ne sais pas pourquoi je crois que ça passait sous GCC. Une très mauvaise habitude en tous cas ^^ "La vie est un grand terrain de jeu. On le sait quand on est enfant mais on l’oublie en grandissant." |
Voir plus haut: ça passe sur GCC, parce que c'est GCC qui a introduit cette extension non standard Membre de la TI-Chess Team. Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP. |
Brunni > C'est le truc qui a été dit plus tôt dans le topic. T'aurais pu lire quand même (cross) T'as un problème ? Tu veux un bonbon ? [CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes |
J'ai même posté les deux liens TIGCC/GNU Merci en tout cas pour cette explication. Pour la priorité des opérateurs, j'utilise ce lien que m'avait filé Bob : http://www.commentcamarche.net/contents/c/cop.php3 Il n'y est pas question d'opérateurs, et je croyais que les casts avaient une priorité encore plus forte. Mais de toute façon, j'avais mal interprêté "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Si j'ai bien comprendru, ces trois formulations sont équivalentes, avec Ptr de type void* et sizeof(short) == 2 : ((short*) Ptr)[1]; *((short*)Ptr + 1); *(short*)(Ptr + 2); ? "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Normalement non ce n'est pas la meme chose, enfin suivant le compilo, et ce qu'il optimise (etc...) tu peux avoir une comportement différent Et l'arithmetique sur void* est a proscrire ^^ (Ptr+1) / (Ptr+2) |
Folco > il me semble que les deux premiers sont équivalents (sauf que je ne suis pas sûr des priorités donc j'aurais tendance à écrire plutôt dans le deuxième cas : *(((short*)Ptr) + 1) ^^) ; pour que le troisième renvoie la même chose ce qu'il faut précisément c'est que Ptr soit de type t* avec sizeof(short) = 2*sizeof(t) Forum Cultures du monde — forum littéraire Membrane fondatrice de la confrérie des artistes flous. L'univers est-il un dodécaèdre de Poincaré ? (``·\ powaaaaaaaaa ! #love# |
En fait pour que le second marche de maniere sure, il faut mieux faire un *(((short*)Ptr) + 1); |
Sally (./186) : Ouah en effet. J'éspère quand même qu'un cast est prioritaire sur une addition quand même. Bon, je vais vraiment devoir lire un truc sur la priorité des casts et le retenir. La surcharge des parenthèses c'est efficace en fiabilité, mais bonjour la lecture. Sally (./186) : Comme pour Godzil, j'ai posé la question au ./172, on m'a répondu en dessous, et j'ai posté les liens au ./176 : j'utilise l'extension GNU de GCC qui donne sizeof(void) == 1. Donc ici, ça marche. Ce n'est ni standard ni portable, mais ça reste parfaitement safe (c'est ça les extensions non-standard). Donc merci bien our vos réponses, je vai choisir la notation que je trouve la plus claire ou la plus adaptée à un cas donné. Donc je ne sais pas encore laquelle je vais choisir en fait. cross -> Godzil : certainement. Mais je vais quand même rechercher quelle est la règle. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Folco > Pour être plus correct, ton *(short*)(Ptr + 2);devrait être *(short*)(Ptr + sizeof(short)); Plus généralement, je dirais que la première forme est préférable à la seconde la plupart du temps. Et la troisième est à proscrire. Et pour être propre (ce qui ne coute rien si ton compilateur optimise correctement), tu devrais déclarer une nouvelle variable short* shortPtr = (short*)Ptr; Godzil > Tu ne veux pas plutôt dire un assembleur généré différent ? Car les 3 devraient quand même donner la même chose il me semble (en supposant un processus monotâche, et une plateforme avec sizeof(short) = 2 évidemment T'as un problème ? Tu veux un bonbon ? [CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes |
Folco (./188) :C'est le cas |
RHJPP -> Ok merci (quand même GoldenCrystal (./189) : Ok. Mais en fait, les deux premiers octets sont la taille d'un fichier sous AMS, AFAIK ce n'est pas défini comme un unsigned short quelque part. C'est juste le cas. Par contre, les deux octets suivants sont définis en tant que tel par moi. Donc un Ptr + 2 ne me choque pas plus que ça dans ce cas-là. Mais ta méthode est plus correcte sur le principe. GoldenCrystal (./189) : Ok. GoldenCrystal (./189) : Je déteste perdre en lisibilité, même si t'as raison, ça ne couterait sûrement rien. Je n'utilise des variables bidon que quand ça simplifie l'écriture justement. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence Voilà, ce tableau donne la réponse. Ca montre aussi qu'un *(truc*)Ptr est parfaitement valide, et vaut la valeur de type truc située à Ptr. Au niveau des priorités, "ça passe juste" mais ça passe "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Folco (./191) : Ben je sais pas exactement ce que tu veux faire en fait. De la façon dont tu présentais ça, j'ai pensé que c'était pour accéder à une liste de short* Si c'est pour sauter des octets en comme un offset, alors évidemment, la troisième solution est à choisir… Enfin, tu aurais pu préciser l'intention quoi. (Et pareil dans ce cas, définir une variable débutFichier = Ptr + 2 peut être utile) T'as un problème ? Tu veux un bonbon ? [CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes |
GoldenCrystal (./189) :Ça ne me semble pas du tout plus propre comme ça Peut-être qu'il faudrait passer par une autre variable, mais il faudrait lui donner un nom plus explicite en relation avec ce qu'elle représente. Il n'y a aucune raison de mettre le type dans le nom, puisque c'est déjà le... type |
Folco (./192) :Euh oui enfin quand ce ne sont que des opérateurs unaires qui se mettent du même côté la question de la priorité ne se pose pas en fait hein ^^. L'étoile ne peut pas s'appliquer à juste (truc*) puisque ce n'est pas un opérande, donc obligatoirement elle s'applique à l'ensemble (truc*)Ptr. Pour qu'il y ait une question de priorité il faudrait qu'il y ait des opérateurs des deux côtés, par exemple *(truc*)Ptr++, là effectivement ça pourrait vouloir dire : (*((truc*)Ptr)++ ou bien *(truc*)(Ptr++) ou bien *(((truc*)Ptr)++) On remarque en passant que si ça devient rapidement illisible, c'est en grande partie grâce à l'idée géniale consistant à utiliser les parenthèses pour écrire l'opérateur de cast alors qu'elles servent déjà à indiquer le groupement, ça c'est une des merveilles du C (merveilleusement reprise en java aussi d'ailleurs, comme la plupart des aberrations syntaxiques du C...) Sinon il y a quelques priorités contre-intuitives (genre >> qui a une priorité super faible) et dans le doute ça va plus vite de surparenthéser que d'aller voir la doc ou de faire des tests ^^. Mais si tu les connais bien effectivement c'est pas nécessaire Forum Cultures du monde — forum littéraire Membrane fondatrice de la confrérie des artistes flous. L'univers est-il un dodécaèdre de Poincaré ? (``·\ powaaaaaaaaa ! #love# |
Attention au fait, caster du char vers des types plus grand peu avoir des effets interessant, que le compilo est INCAPABLE de detecter Adresse Error, Lecture de valeur incohérente (ou incompréhensible) etc... |
RHJPP (./194) : Vu le peu d'explications dans le post de Folco je pouvais pas faire mieux … Et préciser que la variable est un pointeur, ce n'est pas mal, au contraire. Si j'appelle ma variable bananaCount, comment tu sais si c'est un int ou un int* après ? T'as un indice quelque part ? (Sachant que souvent les « variables » ainsi déclarées sont des champs dans des structures plus ou moins obscures ou des variables globales définies à un endroit indéterminé) D'autre part, mettre le nom du type dans la variable, quand c'est autre chose qu'un simple nombre, ça a du sens. Parce que parfois tu veux juste un fruit qui soit un FRUIT, donc tu apelles ta variable fruit… Les assistants de code du langage C étant aussi efficaces aujourd'hui qu'il y a 20 ans (c'est pas tellement de leur faute, ils sont pas gatés avec une telle merde), je vois pas comment tu vas pouvoir deviner le type d'un champ qui est défini dans un .h inclus dans un .h inclus […] dans un .h sans être magicien. (Oui bon, les assistants de code modernes pas trop mal fichus arrivent encore à se démerder avec ça la plupart du temps, heureusement… Mais quand même !) T'as un problème ? Tu veux un bonbon ? [CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes |
Godzil (./196) : Je fais gaffe aux additions de short avec des pointeurs, à cause des extensions de signe du 68k. Il faut toujours marcher avec des unsigned pour obtenir le moveq #0,dn salvateur. Au fait, les extensions, on les retrouve aussi au niveau du x86 ? GoldenCrystal (./197) : J'avoue. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Certains compilos ont des extensions pour ça. Sous Visual Studio, il y a la macro UNALIGNED qui devient rien du tout sur x86, mais peut correspondre à un mot-clé du compilo pour forcer des contrôles lors du déréférencement. |
ArcptrWrite est un unsigned long*, pourquoi n'accepte-t-il pas ça : ArcPtrWrite[1] = ('p' << 16) + ('a' << 8) + 'r'; Même casté en long, il me dit que l'entier ne rentre pas Pourtant mon bouquin dit bien que op1 << op2 décale op1 de op2 bits vers la gauche... Ici, je veux tout simplement un : move.l truc(pc),d0 truc: dc.b 0,"par" Quid ? "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |
Ben un signed ne peut pas rentrer dans un unsigned (et vice-versa), donc tu dois faire un cast vers un unsigned, non ? (Dans ton cas signed long vs unsigned long) T'as un problème ? Tu veux un bonbon ? [CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes |
Peut-être ArcPtrWrite[1] = ((unsigned long)'p' << 16) + ((unsigned long)'a' << 8) + 'r'; Membre de la TI-Chess Team. Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP. |
Folco (./198) :Si tu veux parler d'un truc comme add.w d0, a0, le problème ne se pose pas parce que les instructions x86 ne permettent pas d'utiliser deux registres de taille différente (sauf exception). « Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau |
Ok, merci. "MSVC, le soft qui arrive à générer des problèmes à partir de solutions" © |