90

Folco (./83) :
Le cast en long permet de bosser classiquement sur des entiers non signés
un long, c'est un signed long.

91

Erf, c'est vrai, merci bien. Mais mon code est bien en unsigned. Mais c'est vrai, j'avais pas fait gaffe. cheeky

92

Biennnnnn embarrassed

93

Tiens, euh, d'ailleurs, à propos de cast #sifflote#

J'ai écrit ça :
void *kernel_LibsPtr(LibRef *lib asm("a0"), short function asm("d0"));             // kernel.c de PreOS

        *(long*)((long) Data + *Offset) = kernel_LibsPtr(Descriptor, (short) *Func);

C'est précisément là que j'enregistre mes pointeurs de fonction dans le stackframe.
Ca compile, mais j'ai un warning "Assignment makes integer from pointer without a cast".
Donc je crée un pointeur à partir d'un entier sans cast ?
Où ça ??

Dans l'ordre, on a :
Data est un pointeur de structure casté en long (pour pouvoir faire l'addition de l'offset).
*Offset est un unsigned short
kernel_LibsPtr est un void*
Descriptor est un Libref*, attendu par LibsPtr
*Func est un char casté en short

Le problème vient de la valeur de gauche, l'appel a kernel_LibsPtr seul compile sans warning.
Donc on a :
((long) Data + *Offset) => addition d'un long et d'un short promu en long, ça fait un long
(long*) => il est casté en pointeur
* => c'est là qu'on y met le résultat

Pourquoi ça merde ?


(en asm, ça se résume à move.l a0,offset(a6). C'est rageant de savoir ce que l'on veut et de pas savoir l'écrire. :/)

94

L'addition doit être prioritaire sur le cast.
Essaie :
((long) Data) + *Offsetpour voir.

95

PS : là, tu castes aussi en signed long, c'est voulu ?
Ta structure pointe peut-être sur un signed long, mais le cast pour l'addition devrait probablement être un unsigned long ! Là, tu cours le risque que ((long)Data) soit négatif...
Bon, sur TI, de mémoire les adresse sont sur 24 bits donc ça ne risque rien*, mais c'est une très mauvaise habitude.


* sauf, bien sûr, si tu utilises l'octet libre pour stocker des trucs #modpo#

96

Pen^2 (./94) :
L'addition doit être prioritaire sur le cast.

Ce n'est pas ça sad
Pen^2 (./95) :
* sauf, bien sûr, si tu utilises l'octet libre pour stocker des trucs modpo.img

Hihi grin tu as bien raison sur le principe, mais de toute façon, j'imagine qu'un cast de pointeur en long n'est absolument par portable, par exemple sur 64 bits. Mais t'as raison, c'est sale ^^

97

Ah, je crois que j'ai trouvé :
kernel_LibsPtr renvoie un void*
Or tu stockes ce void* dans un *(long*), autrement dit, un long.
Essaie de caster la valeur de retour de kernel_LibsPtr en long explicitement.
*(long*)(((unsigned long)Data) + *Offset) = (long)kernel_LibsPtr(Descriptor, (short) *Func);

PS : J'ai laissé ton signed long pour ne pas casser ta structure, mais c'est la mort dans l'âme... tongue (je n'avais pas vu que kernel_* renvoyait un pointeur)

98

Folco (./96) :
Hihi biggrin.gif tu as bien raison sur le principe, mais de toute façon, j'imagine qu'un cast de pointeur en long n'est absolument par portable, par exemple sur 64 bits. Mais t'as raison, c'est sale ^^

Faut voir, c'est possible (et même probable) qu'un long devienne 64 bits aussi. Je n'ai plus tout ça en tête, et puis je ne crois pas que ça soit défini de toute façon. L'idée est plutôt du genre (en sizeof) : char <= short <= int <= long, enfin, quelque chose de ce genre.

99

(le long est passé en unsigned long, et toute façon c'est un pointeur de fonction, mais j'écris dedans avec un offset, comme si c'était une simple zone de mémoire et pas une structure #triange#
Pen^2 (./97) :
kernel_LibsPtr renvoie un void*
Or tu stockes ce void* dans un *(long*), autrement dit, un long. Essaie de caster la valeur de retour de kernel_LibsPtr en long explicitement.

Ah, bien vu, c'est ça !

Mais je suis étonné, je croyais qu'en C, void* se castait en n'importe quoi automatiquement, tant que c'est un pointeur. Hors là, je le castais en long*. Mais bon, merci. top

cross:
char <= short <= int <= long, enfin, quelque chose de ce genre.

Avec sizeof(char) == 1 et sizeof(long) >= 2 (je crois).

100

sur x86_64 les long font en effet 64 bits aussi. c'est probablement fait exprès pour que ce genre de cast marche encore grin

101

sur x86_64 les long font en effet 64 bits aussi.

Si on tourne un *nix (LP64), oui. Si on tourne un Win64 (LLP64), non 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.

102

103

Ben oui, les gens s'étaient trop habitués à sizeof(int)==sizeof(long)...
Ils devraient programmer sur TI plus souvent.
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.

104

Ah ? Sur TI c'est pas 32 bits pour les deux ? confus

105

Il me semble bien que sur TI les int font 16 bits, comme les short. Je me suis déjà fait avoir avec ça...
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.

106

Possible.

107

Pen^2 (./97) :
Essaie de caster la valeur de retour de kernel_LibsPtr en long explicitement.
*(long*)(((unsigned long)Data) + *Offset) = (long)kernel_LibsPtr(Descriptor, (short) *Func);

Il est plus propre d'utiliser void ** à gauche (à la place de long *).
Folco (./99) :
Mais je suis étonné, je croyais qu'en C, void* se castait en n'importe quoi automatiquement, tant que c'est un pointeur. Hors là, je le castais en long*.

Le problème n'est pas là, il est dans l'affectation d'un void à une lvalue de type long (pas long *).
Link (./105) :
Il me semble bien que sur TI les int font 16 bits, comme les short.

Exact.
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é

108

Kevin Kofler (./107) :
Il est plus propre d'utiliser void ** à gauche (à la place de long *).

Ah bien vu en effet, je n'avais pas pensé à ça !

extern void CommandHelp(char);
extern void CommandAbout(char);
extern void CommandConfig(char);
extern void CommandFlags(char);

J'ai une erreur parce que je ne passe pas de nom à ce paramètre qui ne m'intéresse pas. La solution élégante du C++ qui consiste à ne pas mettre de nom de variable provoque une erreur en C.
Comment faire, mettre une instruction bidon, genre "char truc++;" dans la fonction ? C'est sale...

109

Bon, ben j'ai adopté la solution crade pour le moment, faute de mieux grin

Sinon, comment peut-on faire pour merger ça :

const char* str = "abc\0def\0ghi\0jkl\0"

et :

const char* str1 = "abc"
const char* str2 = "def"
const char* str3 = "ghi"
const char* str4 = "jkl\0"

? C'est vraiment dommage de devoir doubler les données, sous prétexte qu'en C on ne peut pas mettre de label au milieu sad
Quand à faire du (str+n), même pas la peine, c'est trop crade.

110

mmm, un truc dans ce genre ? Tu ne dois jamais accéder à str directement, bien sûr. Essaie de le cacher au mieux cheeky (c'est pour ça que j'ai écrit private et public, même si ce n'est pas valide en C)
private const char* const str= "abcdcfghijkl" ;
                                012345678901
public const char* const s1= str+0 ;
public const char* const s2= str+3 ;
public const char* const s3= str+6 ;
public const char* const s4= str+9 ;

C'est pas si moche que ça tant que les offsets sont centralisés — en tout cas, c'est déjà mieux que de dupliquer si tu veux mon avis tongue

(Par contre ta déclaration j'espère que c'est du pseudo-code : \d, \g et \j ne correspondent à rien. Et c'est inutile d'ajouter un \0, c'est fait automatiquement par les guillemets.)

111

Oui, en fait je voulais écrire ça :
const char* str = "abc\0def\0ghi\0jkl\0"
C'est en fait des chaines de caractères qui se suivent, terminées par deux \0 (fin du bloc de chaines).
En asm ça donne ça :
dc.b "abc",0,"def",0,"ghi",0,0

Et ok pour les offsets, faut juste pas se planter à compter (les chaines sont un peu plus complexes que "abcdef..." grin).

112

Folco (./111) :
faut juste pas se planter à compter (les chaines sont un peu plus complexes que "abcdef..." biggrin.gif ).

À la rigueur s'il y en a beaucoup tu peux te faire un petit programme annexe qui te concatène tout ça smile

113

Sinon pour la question d'origine, je me demande si dans une structure l'ordre des champs est garanti ou pas...
ça pourrait résoudre ton problème facilement

du genre :
struct {
 const char* s1= "huhu" ;
 const char* s2= "hoho" ;
 char s3= '\0' ;
}


J'en sais trop rien en fait cheeky

114

Tout à fait, ça serit super facile comme ça. Je vais voir si je peux trouver ce que dit la norme à ce niveau.

115

Bon, alors dans mon bouquin, je lis ça :
- les champs d'une structure sont alloués suivant l'odre de leur déclaration
- l'adresse de la structure est l'adresse de son premier élément (donc pas d'octet de padding en début de structure)
- les octets de paddings sont autorisés pour des contraintes d'alignement

Evidemment, ça ne devrait pas être le cas pour des char sur TI. Mais si demain les char sur TI font deux octets, ça pètera. Et si le compilateur décide d'aligner les strings sur des adresses paires parce que ça lui chante, ça pètera aussi, a priori rien ne lui interdit.

116

Folco: une possibilité, pour avoir des sortes de tableaux de strings plus efficaces est utilisée notamment dans le tuto TICT S1P6 et dans Ice Hockey 68k 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.

117

Ah merci super, je cours y voir. Faisant du C que depuis récemment, je ne me suis penché sur ces tutos qu'une fois, très rapidement.

118

Il me semble que ces softs utilisent tous les deux un bout d'ASM, mais il doit pouvoir être remplacé par une expression C, moins compliquée que DEREFSMALL.
avatar
Membre de la TI-Chess Team.
Co-mainteneur de GCC4TI (documentation en ligne de GCC4TI), TIEmu et TILP.
Co-admin de TI-Planet.

119

Pen^2 (./113) :
Sinon pour la question d'origine, je me demande si dans une structure l'ordre des champs est garanti ou pas...
ça pourrait résoudre ton problème facilement

du genre :
struct {
 const char* s1= "huhu" ;
 const char* s2= "hoho" ;
 char s3= '\0' ;
}


J'en sais trop rien en fait cheeky

Il est garanti sinon on utiliserais pas une simple struct pour lire un BMP par example.

Par contre l'endianess il faut faire gaffe
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

120

Ok, donc l'endianness c'est bon à retenir pour les cas généraux, mais codant ti-only ici je m'en fous.

Et les BMP c'est quoi ? Réellement une structure, pas un tableau ? J'ai jamais travaillé dessus en fait ^^ Même avec la SDL, il me suffisait de fournir un fichier en entrée, et la structure qui résultait de la création du sprite était opaque.