30

ah oui tiens ^^
A part que ça peut m'arriver de parcourir le tableau avec une boucle.

Et en ce qui concerne l'utilisations des enum + switch, on peut souvent utiliser des tableaux de pointeurs à la place:
enum z {a,b,c};
switch x {
case a: ...
case b: ...
case c: ...
}
pourrait devenir
tableau[x]();

31

moui enfin si ça te fait déclarer 20 fonctions de 2 lignes, c'est moyen ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

32

Ca revient pas à réécrire le fonctionnement du switch avec sa table de sauts ? smile

33

Non parce que c'est de loin baucoup plus lent tongue
Echanger un ou deux sauts (avec le switch) contre un appel de fonction + sauvegarde d'état + restauration d'état + retour de fonction (avec la table de pointeurs de fonction)... Même sur PC c'est une perte de performances considérable...
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

34

Ben l'avantage (enfin c'est ce que j'ai fait dans foblub) du switch c'est que tu peux déclarer tes 20 fonctions (ou plus) inline et que du coup tu n'as pas l'overhead de l'appel de fonction à chaque fois, alors que si tu fais un tableau de pointeurs c'est obligatoirement compilé comme un vrai appel de fonction même si ta fonction ne fait quasiment rien... donc le tableau de pointeurs n'est vraiment utile que si tu veux pouvoir changer quelle fonction est appelée dans tel ou tel cas, mais si c'est purement statique (ie un nombre donné correspond toujours à la même fonction) le switch est mieux happy

edit : cross
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

35

[HS]c'est quoi foblub ?[/HS]

36

Sally > Sauf que les inline ce n'est plus fiable... Le compilateur peut décider de ne pas inliner ta fonction parce qu'il ne le jugera pas nécéssaire, et en inliner d'autres que tu ne lui aura pas demandé d'inliner, et ce parce qu'il l'aura jugé utile. (ça doit certainement s'appliquer à TIGCC vu qu'il utilise une version assez récente de GCC) Après, j'immagine que si ta fonction n'est appellée *que* dans le switch le compilateur va l'inliner, mais j'en mettrai pas ma main à couper...
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

37

Nheryvra > topics/28956-cherche-beta-testeurs (je crois que c'est le topic le plus récent, je suis pas totalement sûr)

GoldenCrystal > ben ça marchait avec les bonnes options avec une relativement vieille version de tigcc... après ce que tu dis explique peut-être que le programme soit plus gros si je le compile avec une version plus récente :-\.
Mais en même temps s'il faut remplacer les fonctions inline par des macros pour que ça marche ça va être le bordel couic
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

38

Au total j'ai 680 lignes environ de fonctions qui sont toutes déclarées inline, et après j'ai ça :
void execute (word opcode, word num, word *param) {
  switch (opcode)
    {
    case 0x01 : compare(num, param);
      break;
    case 0x02 : LTE(param[0], param[1]);
      break;
    case 0x03 : GTE(param[0], param[1]);
      break;
    case 0x04 : dec_chk(param[0], param[1]);
      break;
    case 0x05 : inc_chk(param[0], param[1]);
      break;
    case 0x06 : check_loc(param[0], param[1]);
      break;
    case 0x07 : bit(param[0], param[1]);
      break;
    case 0x08 : or(param[0], param[1]);
      break;
    case 0x09 : and(param[0], param[1]);
      break;
    case 0x0a : test_attr(param[0], param[1]);
      break;
    case 0x0b : set_attr(param[0], param[1]);
      break;
    case 0x0c : clr_attr(param[0], param[1]);
      break;
    case 0x0d : put_var(param[0], param[1]);
      break;
    case 0x0e : transfer(param[0], param[1]);
      break;
    case 0x0f : load_word_array(param[0], param[1]);
      break;
    case 0x10 : load_byte_array(param[0], param[1]);
      break;
    case 0x11 : get_prop(param[0], param[1]);
      break;
    case 0x12 : get_prop_addr(param[0], param[1]);
      break;
    case 0x13 : next_prop(param[0], param[1]);
      break;
    case 0x14 : plus(param[0], param[1]);
      break;
    case 0x15 : minus(param[0], param[1]);
      break;
    case 0x16 : multiply(param[0], param[1]);
    case 0x17 : divide(param[0], param[1]);
      break;
    case 0x18 : mod(param[0], param[1]);
      break;

      /* Ox19 : gosub à deux opérandes (V4) */
      /* opcodes V5 */
    case 0x1a : if (!ADVANCED) goto illegal;
      gosub (num, param, DROP_RETURN_VALUE);
      break;
    case 0x1b : if (!ADVANCED) goto illegal;
      set_colour(param[0], param[1]);
      break;
    case 0x1c : if (!ADVANCED) goto illegal;
      throw(param[0], param[1]);
      break;

      /*
       * Missing opcodes
       */

      /* opcodes V4 */
    case 0x19 : /* version à 2 opérandes de gosub */
    case 0x2c : if (STANDARD) goto illegal; /* version à 8 opérandes du même */
      /* opcodes V3 */
    case 0x20 : gosub(num, param, 0);
      break;
    case 0x21 : save_word_array(param[0], param[1], param[2]);
      break;
    case 0x22 : save_byte_array(param[0], param[1], param[2]);
      break;
    case 0x23 : put_prop(param[0], param[1], param[2]);
      break;
    case 0x24 : input(param[0], param[1]);
      break;
    case 0x25 : print_char(param[0]);
      break;
    case 0x26 : print_num(param[0]);
      break;
    case 0x27 : pi_random(param[0]);
      break;
    case 0x28 : push(param[0]);
      break;
    case 0x29 : pull(param[0]);
      break;
    case 0x2a : split_screen(param[0]);
      break;
    case 0x2b : set_window(param[0]);
      break;

      /* Ici des opcodes V4...*/

    case 0x33 : output_stream(param);
      break;
    case 0x34 : /* input_stream(param[0]); */
      break;
    case 0x35 : /* sound_effect(num, param); */
      break;

    default :

      if (ENHANCED) switch (opcode)
        {
          /* 0x2c : forme de gosub avec jusqu'à 8 arguments */
        case 0x2d : erase_window(param[0]);
          return;
        case 0x2e : erase_line(param[0]);
          return;
        case 0x2f : set_cursor(param[0], param[1]);
          return;
        case 0x30 : get_cursor(param[0]);
          return;
        case 0x31 : set_font_style(param[0]);
          return;
        case 0x32 : /* buffer_mode(param[0]); */ /* TODO (?) */
#ifdef DEBUG
          if (tracing & 1) scr_putline ("buffer_mode called");
#endif
          return;

          /* Ici des opcodes V3... */

        case 0x36 : read_char(num, param);
          return;
        case 0x37 : scan_table(num, param);
          return;
        }

      if (ADVANCED) switch (opcode)
        {
        case 0x38 : not(param[0]);
          return;
        case 0x39 : /* 8 ops */
        case 0x3a : gosub (num, param, DROP_RETURN_VALUE);
          return;
        case 0x3b : tokenise(num, param);
          return;
        case 0x3c : encode_text(param[0], param[1], param[2], param[3]);
          return;
        case 0x3d : copy_table(param[0], param[1], param[2]);
          return;
        case 0x3e : print_table(num, param);
          return;
        case 0x3f : check_arg_count(param[0]);
          return;
        }
      illegal : error("execute: Invalid Z-code instruction: $%02x", opcode);
    }
}

je ne vois pas comment conserver du code pas trop illisible sans utiliser inline sorry
edit : si je compte bien il y a 53 fonctions, pas 20 grin, mais la plupart font plus de 2 lignes ^^
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

39

Bah regarde le'assembleur généré pour une de tes fonctions (assez grosse si possible) et tu sera fixé happy
Mais pour ce qui est de la taille du programme a mon avis tu dois remercier le nouveau linker qui rajoute beaucoup plus de code (un CRT en quelque sorte :/) qu'avant au 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

40

Le mot-clé inline n'est apparu que depuis le C-99, mais TIGCC (enfin, gcc) ne l'implémente pas encore selon le respect du standard.

Tu peux utiliser le flag -Winline à la compilation pour savoir pourquoi tes fonctions n'ont pas été inlinées (si c'est le cas).

Voici quelques précisions données par la doc de tigcc :
When a function is both inline and static, if all calls to the function are integrated into the caller, and the function's address is never used, then the function's own assembler code is never referenced. In this case, GCC does not actually output assembler code for the function, unless you specify the option '-fkeep-inline-functions'. Some calls cannot be integrated for various reasons (in particular, calls that precede the function's definition cannot be integrated, and neither can recursive calls within the definition). If there is a nonintegrated call, then the function is compiled to assembler code as usual. The function must also be compiled as usual if the program refers to its address, because that can't be inlined.

When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.

If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.
This combination of inline and extern has almost the effect of a macro. The way to use it is to put a function definition in a header file with these keywords, and put another copy of the definition (lacking inline and extern) in a library file. The definition in the header file will cause most calls to the function to be inlined. If any uses of the function remain, they will refer to the single copy in the library.
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. »

41

Pour faire simple : en spécifiant une fonction "static inline", elle est substituée au moment de l'appel.
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. »

42

Sans compter qu'il faut faire gaffe avec l'inline, le compilo peut décider d'inliner la fonction, mais aussi d'ajouter la fonction tel que (cad comme une fonction) dans le code généré... donc ça prend 2x plus de place :/
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.

43

Je comprends toujours pas pourquoi ce topic n'a pas sa place dans "Discussions générales" triso

44

( pasque c'est "Discussions générales" du forum yN -qui n'a a priori rien à voir avec l'info-, et pas du forum Ti 68k ? )
Sinon j'utilise quasiment jamais. (encor du vrai pettern matching ouais, mais un switch, bha sauf 1 ou 2 cas particulier, l'intérêt, ..)
«Les gens exigent la liberté d’expression pour compenser la liberté de pensée qu’ils préfèrent éviter.» - Sören Kierkegaard

La République, c’est comme la syphilis : quand on l’a attrapée, soit on se fait sauter le caisson, soit on essaie de vivre avec.

45

oui ben toutes mes fonctions sont static inline donc ça devrait être bon ^^
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

46

Il est toujours susceptible de ne pas inliner. Il faut utiliser extern inline pour ça.

47

Ah oui mince, j'avais mal lu (ou alors j'avais juste lu le ./41). Effectivement "the effect of a macro" c'est exactement ce que je veux (je veux juste pas utiliser la syntaxe #define parce que c'est trop lourd)
Bon bah pour le coup s/static inline/extern inline/ c'est pas très compliqué à faire ^^
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

48

Ximoon :
Il est surtout très adapté pour le codage d'une machine à états finis, et a le bon goût de garantir un déterminisme évident et lisible.

autant dire que je l'utilise souvent pour un certain projet... #Sifflote#
Tout ce qui passe pas par le port 80, c'est de la triche.

49

Perso je ne l'utilise vraiment, mais alors vraiment jamais grin
Je l'utilisais avant et puis une fois j'ai remarqué qu'en remplaçant le switch par des if / else if, la vitesse s'est multipliée par 3 (et je ne plaisante pas, mais je ne sais pas pourquoi hum). Et comme c'était une boucle qui pouvait gérer un millier d'objets sur un proço à 16 MHz, j'ai pas trop hésité, j'ai viré le switch et depuis je ne l'ai plus jamais utilisé.
S'il y a peu de cas j'utilise des if/elseif, s'il y a beaucoup de cas (comme pour onur) j'utilise une table de fonctions, c'est rapide (surtout si ton proço a un cache) et ça permet de mieux séparer le code pour éviter d'avoir 40000 lignes sur un seul fichier hehe
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

50

Bizarre
avatar
Un site complet sur lequel vous trouverez des programmes et des jeux pour votre calculatrice TI 89 / Titanium / 92+ / Voyage 200 : www.ti-fr.com.
Quelques idées personnelles ici.

51

Ca dépent surtout de la façon don le (pré ?)compilateur fonctionne... c'est pas Sally et Pollux qui avaient eu une discussion sur l'optimisation du switch, et dans quel(s) cas utiliser des if pour aller plus vite ?
avatar

52

C'est fort possible, je ne me souviens plus exactement mais pour si tu regardes l'extrait posté en ./38 tu peux remarquer que j'ai coupé le switch en 3 parties et je crois que je m'étais posé pas mal de questions sur la meilleure façon de faire ^^ (regarde la différence de traitement entre 0x1a-0x1c et 0x2d-0x32, par exemple, elle n'a rien de franchement évident, simplement l'une des plages est plus étendue que l'autre, et il n'y a pas que ça, la table est pleine de bizarreries, je crois que j'avais essayé aussi de faire un seul gros switch, ou alors de couper en plusieurs parties sans aucun trou aussi...)
avatar
« Le bonheur, c'est une carte de bibliothèque ! » — The gostak distims the doshes.
Membrane fondatrice de la confrérie des artistes flous.
L'univers est-il un dodécaèdre de Poincaré ?
(``·\ powaaaaaaaaa ! #love#

53

Brunni :
Perso je ne l'utilise vraiment, mais alors vraiment jamais grin
Je l'utilisais avant et puis une fois j'ai remarqué qu'en remplaçant le switch par des if / else if, la vitesse s'est multipliée par 3 (et je ne plaisante pas, mais je ne sais pas pourquoi hum).

Probablement soit que ton compilo est pas terrible et génère une jump table même qd il y a très peu de cas, ou alors qu'il la génère mal (à une époque le code généré par tigcc pour les jump table était assez bloaté, je sais pas si c'est encore le cas), soit que ton premier cas arrivait nettement plus souvent que les autres et à ce moment-là c'est normal que switch ne soit pas adapté (switch est conçu pour être optimal quand ta distribution est uniforme [probabilité(variable=i)=1/n pour tout i], alors que les if/else if sont optimaux quand ta distribution est géométrique [probabilité(variable=i)=1/2^(i+1)]).
s'il y a beaucoup de cas (comme pour onur) j'utilise une table de fonctions, c'est rapide (surtout si ton proço a un cache) et ça permet de mieux séparer le code pour éviter d'avoir 40000 lignes sur un seul fichier hehe

Je vois pas trop ce que le cache vient faire là-dedans... Et peut-être que dans ton cas ça n'était pas nécessaire, mais dès que tu as besoin d'accéder à des variables locales à la fonction appelante dans ton switch, tu ne peux plus transformer ton switch en table de fonctions (à moins de passer ces variables locales à *toutes* les fonctions que tu appelles, mais ça devient très vite prohibitif si tu as bcp de variables).
Essaye d'écrire un compilo/CAS/n'importe quel truc qui travaille de façon intensive sur des arbres syntaxiques sans switch, tu m'en diras des nouvelles tongue

« The biggest civil liberty of all is not to be killed by a terrorist. » (Geoff Hoon, ministre des transports anglais)