1

Pouet.

J'ai le code suivant :
typedef struct
{
    unsigned short Size;
    unsigned char  FileName [18];
    unsigned char  Tag;
    unsigned char  Extention [5];

} FILE_INFO;

Je veux faire un sizeof (FileName), pour récupérer le 18 proprement. Comment faire ? Zerosquare m'a montré le code d'un gars qui fait bouffer à son compilo un sizeof (FILE_INFO.FileName), mais ça ne passe pas avec GCC.

Voilà, je suis preneur d'une méthode académique si possible, merci d'avance. smile

2

sizeof(((FILE_INFO*)0)->FileName)

3

Merci ! Super comme trick. smile

4

Bon, comme je vais pas créer un topic pour chaque question, je continue ici (comme d'hab grin)

J'ai ce code :
 void* ArchivePtr;
unsigned char* TagPtr;
...
ArchivePtr = (void*) (((unsigned long)TagPtr + 1) & 0xFFFFFFFE); /* Next file is at an even address */

Tout simplement, ça affecte un pointeur à un autre, en s'assurant que ArchivePtr soit bien pair.

Mais je trouve ça très inélégant ces casts, alors que je fais qu'effacer un bit. Ya un moyen plus élégant pour faire ça ?

Mici happy

5

et avec un >> suivi d'un << ça serait pas plus "élégant"? cheeky
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

6

En assembleur, c'est courant, mais est-ce que ça serait pas "optimisé" par le compilateur ?

7

vince > mais ça ne ferait pas la même chose, non ? (ton code aligne sur la valeur paire inférieure ou égale et le code de Folco sur la valeur supérieure ou égale, sauf si j'ai mal lu)
Pour aligner sur la valeur basse, autant faire un &0xFFFF...FFE que deux décalages à mon avis.

Folco > une union ? Tu n'as pas de cast, mais bon, c'est pas forcément plus joli.

8

Attention, de nos jours il faut caster en uintptr_t plutôt qu'en unsigned long.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

9

Ah excellent, Link, c'est devenu un standard de C++ 2011. Bon ben
!call Lionel Debroux
--- Call : Lionel Debroux appelé(e) sur ce topic ...
Faut rajouter le header kivabien pour GCC4TI cheeky

Pen^2 -> yep, j'avais pas pensé.
Pen^2 (./7) :
le code de Folco sur la valeur supérieure ou égale

yes smile
Pen^2 (./7) :
Pour aligner sur la valeur basse, autant faire un &0xFFFF...FFE que deux décalages à mon avis.

En asm, ça serait un 0xFFFE. Beaucoup plus rapide et court qu'un $FFFFFFFE. Mais avec les promotions et les casts, je ne sais pas si c'est possible en C, bien que sur le papier ce serait tout à fait ce qu'il faut faire. Ca donnerait ça :
ArchivePtr = (void*) (((unsigned long)TagPtr + 1) & 0xFFFE);
Ca irait à votre avis ?

10

GCC4TI a le header standard C99 stdint.h, comprenant entre autres uintptr_t, depuis septembre 2008, avant la première release publique wink

$ grep -Rn "uintptr" $TIGCC/include/c
.../gcc4ti/include/c/stdint.h:79:typedef unsigned long uintptr_t;


Et pour info, si tu rencontres plus tard le besoin de connaître le décalage, par rapport au début de la structure, d'un des champs: c'est offsetof, défini par C99 dans stddef.h, et disponible dans le stddef.h de TIGCC et GCC4TI, qu'il te faut.
Ce que PpHd a écrit en ./2 a la même base qu'une définition assez portable d'offsetof, et tu pourrais donc probablement calculer la même chose avec une différence d'offsetof, mais c'est moins simple.

Il y a encore une autre solution: utiliser un #define / une définition constexpr C++11 / à la rigueur une enum (ou une des diverses autres façons de définir une constante, mais si tu n'utilises pas les bonnes, il y aura une variable constante qui prendra de la place dans ton programme ^^) pour la taille du champ filename, et utiliser ce #define quand tu veux savoir quelle est la taille du champ smile
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

11

Folco (./9) :
ArchivePtr = (void*) (((unsigned long)TagPtr + 1) & 0xFFFE);
Euh non, ça ne va pas marcher, ça. Tu vas détruire les bits 31 à 16 de ton pointeur.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

12

Merde, quel con. >< En en castant en (unsigned long) ((unsigned short) TagPtr) ?

13

C'est pareil, en castant en short tu détruis les bits supérieurs.

Bon, quand même, là tu es franchement dans la micro-optimisation et c'est pas recommandé tongue
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

14

Zerosquare (./13) :
C'est pareil, en castant en short tu détruis les bits supérieurs.

Il est pas capable de dire "ok, je fous la paix aux 16 bits du haut et je fais mon and que sur les premiers", et donc laisser les bits du haut en l'état ? C'est le mécanisme de ce cast que je ne comprends pas, j'ai du mal à démêler ce qu'il fait, même si je sais exactement ce que je voudrais qu'il fasse grin
Zerosquare (./13) :
Bon, quand même, là tu es franchement dans la micro-optimisation et c'est pas recommandé

Yep, mais j'ai toujours un peu de mal avec les mécanismes de cast et surtout de promotion.

15

Folco (./14) :
Yep, mais j'ai toujours un peu de mal avec les mécanismes de cast et surtout de promotion.
Le cast pour les entiers n'est pas bien complexe :
- si tu castes vers un type qui a le même nombre de bits, les bits sont préservés tels quels (donc un cast unsigned truc vers signed truc ne modifie pas les données, juste leur interprétation ; ça veut dire qu'il y aura un wraparound si tu essaies de convertir un nombre négatif en unsigned, ou un nombre trop grand en signed)
- si tu castes vers un type qui a davantage de bits, les bits supplémentaires de gauche sont mis à zéro si le type source est unsigned, ou remplis avec le bit de signe si le type source est signed.
- si tu castes vers un type qui a moins de bits, les bits en trop à gauche sont simplement tronqués.

En pratique, ça a pour effet que si la valeur d'origine est représentable dans le type destination, la valeur est conservée. Sinon, elle sera fausse évidemment, mais tu conserves les bits existants autant que possible.

(c'est de mémoire, mais mon K&R est resté au boulot hehe)

Pour la promotion, goto K&R, parce que j'ai toujours un doute et que je ne veux pas raconter de conneries tongue
(et je ne suis pas le seul visiblement, les règles de codage MISRA utilisées pour les systèmes sécuritaires mettent explicitement en garde contre les risques de la promotion et le fait que beaucoup de programmeurs n'y font pas attention)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

16

PpHd (./2) :
sizeof(((FILE_INFO*)0)->FileName)

Par contre je crois que ça ne tient pas compte de l'alignement (genre si ton membre est un char et que tu mets un long plus loin). Il faudrait calculer la différence d'adresse entre le membre et le prochain, j'imagine.
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

17

Effectivement. Y'a offsetof() pour ça : [url]http://en.wikipedia.org/wiki/Offsetof [/url]
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

18

Brunni (./16) :
Par contre je crois que ça ne tient pas compte de l'alignement

Est-ce important dans mon cas ? Je veux surtout que ça ne tienne pas compte de l'alignement, que ça me renvoie la véritable taille du champs, indépendamment d'un éventuel padding.

19

Ça renverra bien la taille du champ, pas la taille + le padding.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

20

je rappelle aussi au zazard __attribute__((packed)) pour éviter les alignements ajoutés par le compilateur.

21

(pas portable, malheureusement, même s'il existe des équivalents sur les autres compilos ; et potentiellement risqué sur 68000 aussi, si tu fais pas gaffe tu peux te retrouver avec un word ou un long sur une adresse impaire)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

22

voui faut faire gaffe à l'alignement, je rappelais la feature au cas où, pas spécialement pour ce cas.

23

Yep, je connais cet attribut, effectivement en 68k faut savoir ce qu'on fait avec ça.

24

Link (./8) :
Attention, de nos jours il faut caster en uintptr_t plutôt qu'en unsigned long.

Dans une ABI bien fichue (genre celles de tous les portages de GNU/Linux), uintptr_t, size_t et unsigned long ont tous exactement la même taille, il n'y a que l'ABI W64 qui sux. tongue

Cela dit, uintptr_t existe depuis 1999, il serait effectivement temps de l'utiliser. (Mais la même plateforme pourrie qui a une ABI tordue est aussi celle qui n'implémente toujours pas complètement le C99 dans son compilateur officiel, 13 années après sa standardisation! bang)
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

25

Tu trolles, partir du principe que sizeof(unsigned long) == sizeof(void *) a toujours été une erreur, ce n'est pas parce que ça marchait avant que c'était garanti. Et si MS a fait ce choix, ce n'est pas par hasard, renseigne-toi un peu.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

26

Ils ont jugé qu'il y a plus de code qui dépend de sizeof(long)==4 que de sizeof(long)==sizeof(void*). AMHA, c'était un mauvais jugement, et surtout très à court terme, le reste du monde utilisant le modèle LP64, et donc le code 64-bit-safe étant développé pour sizeof(long)==8 maintenant. Du coup, W64 est gratuitement incompatible avec le reste du monde.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

27

AMHA, ce qu'ils auraient dû faire, ça aurait été de garder leurs typedefs de type LONG qu'ils utilisent de partout dans leur API de toute façon, et de faire un typedef int LONG; plutôt que typedef long LONG; tout simplement, ça aurait gardé la compatibilité des APIs tout en utilisant le modèle LP64. Ils avaient déjà fait ça pour W16→W32 d'ailleurs, cf. WPARAM qui a la même taille que LPARAM dans SendMessage en 32 bits.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

28

Dans le blog de Raymond Chen, il explique comment ont été prise les décisions pour le passage W32->W64. Je n'ai pas tout lu, mais à mon avis s'ils n'ont pas fait ce que tu dis, il y a une bonne raison.

Mais de toute façon, c'est une bonne chose : présupposer sizeof(long) == 8, tout comme présupposer sizeof(long) == sizeof(void *), c'est crade et pas garanti. Du coup, les applications qui voudront être portables devront utiliser int64_t, qui est la solution la plus propre, et ça sera bénéfique à tout le monde tongue
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

29

Je ne suis pas d'accord avec Kevin pour LLP64, quand on dépend autant de la compatibilité c'est le meilleur choix (même si ILP64 n'est pas si loin derrière).
Kevin Kofler (./24) :
(Mais la même plateforme pourrie qui a une ABI tordue est aussi celle qui n'implémente toujours pas complètement le C99 dans son compilateur officiel, 13 années après sa standardisation! bang)

C'est encore pire que tu le crois: Ils ont carrément dit qu'on pouvait s'asseoir sur C99 et C11, qu'ils ne l'implémenteraient jamais. Ils ont officiellement décidé de ne supporter que C++11 et C90.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

30

Ça par contre, c'est lamentable.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo