300

Même sur PC, Kevin est pour l'optimisation taille. grin

301

Chose que je trouve assez absurde. Ce qui compte, c’est la taille de l’exécutable généré et la lisibilité du code.
avatar
« Quand le dernier arbre sera abattu, la dernière rivière empoisonnée, le dernier poisson capturé, alors vous découvrirez que l'argent ne se mange pas. »

302

La taille de l'exécutable généré c'est complètement subjectif et dépendant de la problématique.
Mais réduire la taille du code avant compilation c'est effectivement sans intérêt grin
Y'a après une différence entre ce que fait Kevin, qui est compresser le code à outrance (au point même d'en perdre la vraie signification), et compresser plusieurs lignes en une seule.
while (i != 0)
{
    i = i - 1;
}
Par exemple c'est complètement redondant. Le fait que le "= i - 1" puisse être optimisé en "-= 1" ou "--" est laissé au choix du codeur, de préférence sur des critères de lisibilité du code.
Pour le reste, les { } sont par exemples inutiles (oui je les ai volontairement mis pour ça) donc ça va répartir le "code utile" inutilement sur 4 lignes au lieu de 2.
Ensuite le (!= 0) est par définition du langage C fait implicitement (implicitement mais de manière explicite, vous suivez ? tongue) par les structures du langage C (sinon on pourrait aussi écrire if (i != 0 != 0 != 0 != 0 != 0 [...]) jusqu'à obtenir comme résultat un bool, mais on peut attendre très longtemps...)
le i-- (ou équivalent) peut carrément être mis à l'intérieur du while.while (i--) ;Ensuite, oui,Est-ce vraiment moins clair ? Je trouve que ça a presque gagné en lisibilité moi.

Sinon, pour l'utilisation des trucs réducteurs tels que ++ et += par exemple, ce que je fais par exemple: (Règle 1 pour tous les <opérateur>=; Règle 2 uniquement pour += et -= )
1. Si c'est une opération "+ valeur" uniquement, réduire en "+=". Si c'est un "+ valeur1 + valeur2" alors non.
2. Si c'est réduit en "+=": Si c'est un "+ 1", et que ce n'est pas dans une série de "+=" (ou <opérateur>= quelconque), réduire en ++.

Aussi, l'espacement du code est important. Pas à outrance, mais encadrer les opérateurs binaires par des espaces, et insérer des lignes vides entre des blocs d'instructions sans grand rapport. Donc entre les fonctions, mais aussi dans les fonctions ^^
Certains voudront même mettre plusieurs lignes vides, mais en général au delà de 2 c'est clairement abusif et ça diminue la lisibilité plus qu'autre chose. (deux c'est déjà limite...)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

303

Pour le "!= 0" c'est un sujet qui (comme beaucoup d'autres hehe) a déjà été abordé sur yAronet, et je suis du même avis qu'une majorité de yNautes (il me semble), à savoir que la seule chose à prendre en compte est le sens que porte la variable comparée :

- Quand on compare une variable numérique (un compteur par exemple), le "!= 0" et le "== 0" ne devraient pas être retirés. Oui ils sont implicites, mais on veut comparer sa valeur, donc un nombre. À partir de là on écrit pas "if (count)" en se disant qu'on est un vraie génie à avoir économisé 4 caractères, mais "if (count != 0)" ou "if (count == 0)" en se disant que "vérifier si le nombre d'éléments dans mon tableau est vrai", ça n'aurait aucun sens.

- À l'inverse, quand on compare une variable qui est utilisée comme booléen, il serait stupide d'écrire "== 0" ou "!= 0" : on ne veut pas la comparer à zéro, on veut savoir si elle vaut vrai ou faux. Donc "if (flag)" ou "if (!flag)".
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

304

Hmm oui c'est vrai ( ./83 ^^) le cas de la boucle vide ça marche bien sans le != 0 parce que c'est une sémantique type booleen cheeky
(i-- > 0) faire_quelque_chose(i);Dans le cas pratique c'est plutôt while
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

305

Tiens, mon promier problème avec "static", que je ne connais pas. J'ai un Masked Big Sprite de Genlib, que j'initialise comme ça :
  MBGS Cursor =
  {
    16,
    1,
    {
      0xFF
    }
  };

Le sprite est faux en dimension mais osef.
Si je ne le déclare pas en static, j'ai l'erreur :
error: non-static initialization of a flexible array member (near initialization for 'Cursor')
Quand je rajoute "static" à la déclaration, ça marche sans problème. Mais pourquoi ? Qu'est-ce que ça change ? Qu'est-ce que ça signifie dans ce contexte ? Pourquoi il n'y en a pas besoin pour mes autres données ? confus

306

Le type Cursor est de taille variable, donc ne peut pas être alloué sur la pile.
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é

307

Donc je suis obligé de lui dire moi-même qu'il ne va pas bouger ?

308

Oui, et c'est à peu près ce que fait static. smile
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é

309

Bon, je suis toujours embêté avec les libs dynamiques et la compilation.
Il y a des relogements, en soi pour le coup je m'en fous, mais tant qu'à faire j'aimerais bien les virer puisqu'il sont marqués comme "removables", et apparemment c'est pas fait.

J'ai mis ça dans kernel.h :
#define main _main
#define _main __main
#undef _main

(made in PpHdland)

Résultats des compilations :
tigcc -v -Wall -W -O2 -mno-bss --optimise-code --cut-ranges --reorder-sections --remove-unused -ffunction-sections -fdata-sections [...]

Program Statistics:
  Program Variable Name:                    main\asti68k
  Program Variable Size:                    634 Bytes
  Absolute Relocs:                          6
  Natively Emitted Relocs:                  0
  Relocs Removable by Move Optimization:    10
  Space Savable by Using GAS `-l' Switch:   20 Bytes

Pour optimiser ça, puisqu'il dit pouvoir le faire, j'utilise -mpcrel :
======================================================================
*** Warnings ***
asti68k.o: Warning: Library calls cannot be relative; changing to absolute.
asti68k.o: Warning: Library calls cannot be relative; changing to absolute.
asti68k.o: Warning: Library calls cannot be relative; changing to absolute.
asti68k.o: Warning: Library calls cannot be relative; changing to absolute.
asti68k.o: Warning: Library calls cannot be relative; changing to absolute.
======================================================================
*** Errors ***
asti68k.o: Error: Cannot emit 2 byte library call to `butillib', function 0x0.
asti68k.o: Error: Cannot emit 2 byte library call to `butillib', function 0x2.
asti68k.o: Error: Cannot emit 2 byte library call to `butillib', function 0x3.
asti68k.o: Error: Cannot emit 2 byte library call to `butillib', function 0x6.
asti68k.o: Error: Cannot emit 2 byte library call to `butillib', function 0x1.
/opt/gcc4ti/lib/tigcc.a: Error: Library calls are not supported in this mode.
======================================================================

Alors, ce que je comprends, c'est que je lui demande de tout faire en pc-relatif. Il me balance un warning pour me dire qu'il peut pas écrire les appels de dll en pc-rel, c'est évident, il passe en absolu, très bien.
Mais alors pourquoi ces erreurs après ? Qu'et-ce qui lui va pas encore ? An'a marre ... cry

310

C'est --optimize-code, pas --optimise-code.

Et tu ne peux pas utiliser -mpcrel avec des libcalls. Un libcall est forcément un relogement.
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é

311

Ok, je pensais qu'il savait se dire "je passe tout en pc-relatif sauf les libcalls, puisque évidemment c'est pas possible". Merci bien. smile

312

J'ai ce code C :
	BufferSize1 = InitHandle(&Buffer1, BufferSize1, Name1);
	BufferSize2 = InitHandle(&Buffer2, BufferSize2, Name2);
	BufferSize3 = InitHandle(&Buffer3, BufferSize3, Name3);
	BufferSize4 = InitHandle(&Buffer4, BufferSize4, Name4);

Qui donne ça :
.LC1:
	.ascii "ab\0"
.LC2:
	.ascii "cd\0"
.LC3:
	.ascii "ef\0"
.LC4:
	.ascii "ghijklm\0"
	.section	.text._main,"x"
	.even
	.globl	_main
_main:
	link.w %fp,#-20
	movm.l #0x1830,-(%sp)
	clr.b -1(%fp)
	pea .LC1
	pea 10.w
	pea -4(%fp)
	lea InitHandle,%a2
	jbsr (%a2)
	move.l %d0,%d4
	pea .LC2
	pea 10.w
	pea -6(%fp)
	jbsr (%a2)
	pea .LC3
	pea 10.w
	pea -8(%fp)
	jbsr (%a2)
	lea (32,%sp),%sp
	move.l #.LC4,(%sp)
	pea 10.w
	pea -10(%fp)
	jbsr (%a2)

Pourquoi ce move.l #.LC4,-(%sp) ? Pourquoi pas un pea comme les autres ? Il me fout un relogement pour ça, c'est nul comme comportement confus Pourquoi, quel intérêt ? Et pourquoi procéder de deux manières différents pour deux cas strictement identiques ??
Et si je vire n'importe lequel de ces 4 appels de fonction, le relogement dégage... Comment forcer ça ??

313

Attention, si tu regardes le code, tu verras qu'il n'y a pas de '-' devant "(%sp)", ce qui fait que cette instruction est différente d'un PEA.
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.

314

Oui je sais (je me suis planté au-dessus), mais le problème n'est pas là. Il fait ça pour ne pas avoir à dépiler 4 octets, je fais ça aussi en assembleur. Mais 4 octets de pile, j'en ai rien à battre, pourquoi fait-il ça ? Pourquoi un relogement ? On perd plus de place de binaire que 4 malheureux octets de pile dont on a rien à foutre

315

Parce que l'optimisation sur le register transfer language (RTL) qui fait ça n'est pas au courant des détails du jeu d'instruction 68k, probablement.
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é

316

Et ya u moyen d'avoir un adressage relatif, même avec les appels de libs ? En sortant les appels de dll et en les mettant dans un autre fichier, puis en compilant séparément avec différentes options peut-être ?

317

Et l'intérêt? Si tu as des appels de libs, tu as forcément des relogements, donc je ne vois pas pourquoi tu cherches à éviter les relogements internes à tout prix.
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é

318

Aucun intérêt c'est sûr. C'est juste que je voulais virer ce relogement que rien ne justifie techniquement.

319

J'attends ton correctif pour GCC. tongue
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é

320

Tu sais très bien que je peux pas y arriver j'ai pas le niveau. grin Maintenant, je suis sûr que d'autres vont le faire, merci d'avance à tous ! top #espoir#

321

322

Autre question.
Si j'écris : return a-- + 1;
avec a type de base non pointeur (pour faire simple).

Est-ce exécuté comme ça ?
1. on stocke ret = a + 1
2. on décrémente a
3. on retourne ret = a + 1

Ou comme ça ?
1. on calcule ret = a - 1 + 1 (vu que a-- + 1 == a)
2. on décrémente a
3. on retourne ret = a

En fait, je ne sais pas ce que doit faire le langage :
- évaluation de l'expression, décrémentation de a et retour de l'expression réévaluée après la décrémentation
- évaluation de l'expression, retour de la valeur obtenue, et décrémentation de a juste avant le retour effectif

Ca me parait ambigu, et je n'ai pas trouvé dans mon bouquin quel est le comportement attendu et garanti dans ce cas-là.

edit -> rah je voulais parler d'un a-- et non d'un --a pour lequel c'est évident...

323

Folco (./322) :
Est-ce exécuté comme ça ?
1. on stocke ret = a + 1
2. on décrémente a3. on retourne ret = a + 1
Tes deux ret ont-ils la même valeur ? Sinon, pourquoi stocker une valeur inutile ?

Dans la seconde proposition, pourquoi décrémenter a deux fois ?

Tu peux simplement faire en premier les préincrémentations et prédécrémentations puis faire le calcul. Appliquer les postincrémentations et postdécrémentations et enfin retourner le résultat.
avatar

324

La réponse à ta question est très simple Folco:
Tu peux considérer que --a est équivalent à (a -= 1), autrement dit équivalent à (a = a - 1). (Idem pour ++a)
C'est une pré-décrémentation (resp. pré-incrémentation) donc le comportement est simple, tu sais qu'elle a toujours lieu avant le reste des calculs, le reste n'a pas dimportance:
L'ordre où le stockage "physique" des variables est effectué peut varier selon le compilateur et les optimisations, et n'a par conséquent aucune importance (ton --a pourrait même ne jamais avoir lieu), et sauf exception, ça n'influencera jamais le déroulement logique de ton programme.
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

325

C'est pas ça que je demande, j'ai dû mal m'exprimer. Je veux savoir le comportement d'un 'return a-- +1', quelque soit ce que je veux faire.

CROSS ! Mon problème me semble évident avec un --a en effet, mais je pensais à a--, ce qui change tout (j'ai édité le post de ma question en remplaçant en conséquence).

326

return --a + 1; est équivalent à --a; return a + 1;.
return a-- + 1; est équivalent à tmp = a + 1; --a; return tmp; ou à plus bas niveau %d0 = a + 1; --a; rts;.
C'est la différence entre prédécrémentation et postdécrémentation.

Maintenant, le compilateur n'est pas con, si a est local, il va optimiser ton return --a + 1; en return a;. smile
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é

327

./325 > Ah c'est malin cheeky
Ben c'est un peu plus chiant car le post-incrément est effectué "après".
Mais c'est globalement pareil.
La norme te garantit que a++/a-- vaut a au moment de l'évaluation, et que a sera incrémenté/décrémenté après. (Je sais plus si "après" est directement après le ++/-- comme en C# ou à la fin de la ligne de code par contre, flemme de regarder, et de toutes façons il suffit de pas mettre deux ++/-- sur la même variable sur la même ligne tongue)
Donc tu fais return a-- + 1;
ça fait a + 1; ET a = a - 1; ET return "valeur";
Le reste est sans importance tongue
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

328

Ok ! Donc le '++' est exécuté après le calcul de toute l'expression.

Dans mon programme, 'a-- + 1' est un peu plus complexe, il s'agit de ça en réalité :const char *GetNextArg(CMDLINE *Parser) { Parser->ArgIt++; return Parser->ArgV[Parser->ArgIt - 1]; }
Je me demandais si j'aurais pu écrire : return Parser->ArgV[(Parser->ArgIt)++];
Pour retourner Parser->ArgV[Parser->ArgIt], puis incrémenter Parser->ArgIt
Ca fait bizare de se dire que les choses vont se passer comme si on effectuait une opération (en l'occurrence, l'incrémentation) après le retour. cheeky

re-GC-cross : Voilà pourquoi j'ai écrit en deux lignes grin

329

Oui ça peut te sembler un peu bizarre avec le coup du return, mais si tu réfléchis un peu, la ligne de code est éxécutée, le compilateur peut pas en zapper la moitié juste comme ça.
Donc ton ++/-- est forcément éxécuté quoi qu'il arrive (sauf bien entendu, si tu utilises des opérateurs de court-circuitage && ou || en même temps tongue)
En fait le return est une opération en deux temps (dans le cas où il y a une valeur de retour), ① obtenir la valeur de retour ② quitter la fonction.
Toutes tes opérations seront quoi qu'il arrive terminées avant le ② smile
Après ce qui compte est le comportement "apparent" donc le compilateur peut optimiser ça comme il veut, changer l'ordre de tes opérations, l'ordre des lignes de code, supprimer des opérations, etc… Mais ça ne te regarde pas smile
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

330

(cross)
./328 : dans ton cas, l'écriture en une ligne est aussi correcte et plus claire je trouve (tu peux aussi virer les parenthèses)

sinon non, le ++ est exécuté avant le calcul de l'expression, c'est juste que GC a présenté le déroulement déjà optimisé par le compilo
sans optimisation, ça donne a1 = a; a = a + 1; ret = a1 + 1; return ret; et c'est ce comportement qui doit être conservé
avatar