1

Juste un petit post bookmark sur quelques MACROS en C sur des truc que je ne pensais même pas que ca soit faisable (Attention! C'est du preprocessing C99 de haut niveau)

+ Programmation fonctionnelle (macros lambda):
https://github.com/Leushenko/C99-Lambda
namespace(myFunctionList, typedef int(* fptr)(void); fptr functions[] = { fn(int, (void), { return 1; }), // Simple function literals fn(int, (void), { return 2; }), fn(int, (void), { return 3; }) }; )

+ Macros MAP pour appliquer une MACRO à une liste d'argument
https://github.com/swansontec/map-macro

MAP(f,x,y,z)
==> f(x) f(y) f(z)


+ Un ensemble de macros assez utile pour méta programmer son préprocessing (avec une méthode pour faire de la récursion de MACRO !)
https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms

Exemple:
macro WHEN, IF, EQUAL,WHILE, ... //An example of using this macro #define M(i, _) i EVAL(REPEAT(8, M, ~)) // 0 1 2 3 4 5 6 7
+ il existe aussi ce tutoriel sur le sujet http://jhnet.co.uk/articles/cpp_magic et sa librairie sur le sujet: https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h

+ P99: une librairie de macros diverses et variées:
http://p99.gforge.inria.fr/p99-html/

+ m*lib : https://github.com/P-p-H-d/mlib

2

W.T.F.

Nice.

3

Finalement, on devrait programmer en directives C, c'est bien plus puissant que le langage lui-même. cheeky

Sinon, j'ai rien pané, on est quand même dans le préprocessing de l'espace, là grin

Et sinon, je comprends pas la syntaxe de la toute première, ça existe namespace en C ? oO

4

namespace n'existe pas en C, le nom est juste donné à une macro pour 'planquer' tout le bazard. J'suis encore en train de lire le code. grin

5

J'ai écrit une macro ADD qui additionne 2 nombres entiers trilove /* ADD: Through recursivity: */ #define ADD_L0_INDIRECT() ADD_L0 #define ADD_L1(x,y) DELAY3(ADD_L0_INDIRECT) () (INC(x), DEC(y)) #define ADD_L0(x,y) IF(BOOL(y)) (ADD_L1(x,y) , x) #define ADD(x,y) EVAL(ADD_L0(x,y))
avec ADD(13,15) qui donne après cpp :
28

donc c'est encore valable comme token de préprocessing trilove

Comme çà, je vais pouvoir écrire les macros SUB et CMP. Puis faire d'autres trucs avec. Je suis en train de me construire tout un nouveau langage devil

6

lol


GT rabbit
avatar
Accrochez vous ca va être Cerebral !!

7

T'as plus qu'à faire des macro bsr et lea, et je me mets au cpp !

8

lol



GT Mdr !!
avatar
Accrochez vous ca va être Cerebral !!

9

Petite macro C11 écrite à l'instant (et utilisant la macro MAP référencée précédemment - ou autre implémentation de cette macro): #define PRINTF_FORMAT(x) _Generic(((void)0,x), \ char: "%c", \ signed char: "%hhd", \ unsigned char: "%hhu", \ signed short: "%hd", \ unsigned short: "%hu", \ signed int: "%d", \ unsigned int: "%u", \ long int: "%ld", \ unsigned long int: "%lu", \ long long int: "%lld", \ unsigned long long int: "%llu", \ float: "%f", \ double: "%f", \ long double: "%Lf", \ const char *: "%s", \ const void *: "%p", \ char *: "%s", \ void *: "%p") #define PRINT_ARG(x) printf(PRINTF_FORMAT(x), x); #define PRINT(...) do { MAP(PRINT_ARG, __VA_ARGS__) } while (0) permettant de faire: const int x = 142; PRINT("Ceci est un test. x=", x, " et le flottant vaut ",17.42,"\n"); et affichant bien:
 Ceci est un test. x=142 et le flottant vaut 17.420000
(Marche avec gcc et clang)

10

top
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

11

Ah oui c'est chouette ça !

12

Pas mal happy
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

13

Oula, bientôt un Boost en C? gni

./9 → Pourquoi le (void)0,?
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é

14

J'avoue: simple et efficace. smile

./13: Le (0,x) est nécessaire pour transformer le x (de telle sorte que char [4] ==> char*, autrement ca ne passe pas avec clang). Cf. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1930.htm https://gustedt.wordpress.com/2015/05/11/the-controlling-expression-of-_generic/ et http://stackoverflow.com/questions/18857056/c11-generic-how-to-deal-with-string-literals
le (void) est nécessaire pour faire taire les warnings de gcc.

15

Excellent love
So much code to write, so little time.

16

A noter que (0,X) ne marche pas en C++ (Différence d'implantation entre le C et le C++ sur l'opérateur ',': en C on ne peut pas générer de lvalue, mais en C++, on peut) et qu'il faut utiliser alors (X)+0 dans ce cas (mais alors, on a la promotion entière et on perd la possibilité d'afficher les char et les short) < de toute façon, c'est inutile en C++ >

17

Bien sûr, ces techniques n'ont pas échappé au projet Boost:
http://www.boost.org/doc/libs/release/libs/preprocessor/
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é

18

Boost n'utilise pas toutes ces techniques (mais il en utilise et il en utilise aussi d'autres).

Sinon petit apéritif: #define SEQ_L0_INDIRECT() SEQ_L0 #define SEQ_L0(current,end,f) IF(EQUAL(current, end))( f(current) , SEQ_L1(current, end, f)) #define SEQ_L1(current,end,f) f(current) , DELAY3(SEQ_L0_INDIRECT) () (INC(current), end, f) #define SEQ(init,end,f) EVAL(SEQ_L0(init,end,f)) ==> SEQ(2,5,ID) /* ==> */ ID(2), ID(3), ID(4), ID(5)
avant le plat principal que je prépare.

19

Bon allez je m'attaque au polymorphisme en C. Bon je sais plein de gens l'ont fait avant moi (cast, macro, ...), mais la petite méthode que je viens juste de mettre au point est assez originale je pense ! (Elle remplace pas les autres, elle est surement bourrée de bugs et de limitations, mais bon, je suis super content d'y être arrivé. Ça me trottait dans la tête depuis des mois (en me disant, ça doit être possible, ça doit être possible) )
Évidemment, ce n'est pas miracle (faut pas rêver, le C++ n'a été conçu que pour ajouter le polymorphisme au C).

Après avoir inclut la librairie de préprocessing : #include "m-macro.h" on définit où on veut les prototypes des méthodes (on peut mettre ce qu'on veut mais il faut les définit avant de définir les classes qui les utilisent - normal, non ?) : /* Define generic INIT method */ #define PROTO_METHOD_INIT(type, alias) void (*alias)(type) #define INIT(...) M_CALL_METHOD(INIT, __VA_ARGS__) /* Define generic CLEAR method */ #define PROTO_METHOD_CLEAR(type, alias) void (*alias)(type) #define CLEAR(...) M_CALL_METHOD(CLEAR, __VA_ARGS__)
puis on définit les classes avec leurs méthodes (exemple avec GMP): #include <gmp.h> /* Register new class: mpz_t */ #define TYPE mpz_t #define CLASS INIT, mpz_init, CLEAR, mpz_clear #include M_REGISTER_CLASS /* Register new class: mpq_t */ #define TYPE mpq_t #define CLASS INIT, mpq_init, CLEAR, mpq_clear #include M_REGISTER_CLASS
puis on les utilise et la bonne fonction sera appelée automatiquement : void f(void) { mpz_t a; mpq_t q; INIT(a); INIT(q); CLEAR(a); CLEAR(q); } Cela génère le code suivant sans erreur ni avertissement : f: subq $56, %rsp movq %rsp, %rdi call __gmpz_init leaq 16(%rsp), %rdi call __gmpq_init movq %rsp, %rdi call __gmpz_clear leaq 16(%rsp), %rdi call __gmpq_clear xorl %eax, %eax addq $56, %rsp ret
Une classe n'a pas à implanter toutes les méthodes existantes, juste celles qu'elle supporte.
C'est surement bourré de limitations, mais c'est C11 compliant (pas d'extension), ça n'utilise aucun cast en interne (tout est type safe) et je suis super content d'y être arrivé love
Les méthodes et les classes sont décorrélés (elles peuvent donc être dans des header différents), et çà c'est super cool top

Plus fort. Mettons que le code plus loin enregistre une nouvelle classe (donc après que certaines méthodes aient déjà été utilisées): /* Define generic COPY method */ #define PROTO_METHOD_COPY(type, alias) void (*alias)(type, const type) #define M_COPY(...) M_CALL_METHOD(COPY, __VA_ARGS__) /* Register new class: mpf_t */ #define TYPE mpf_t #define CLASS INIT, mpf_init, CLEAR, mpf_clear, COPY, mpf_set #include M_REGISTER_CLASS
et ben le code suivant marche ! top int g(){ mpf_t a; INIT(a); CLEAR(a); return 0; }
On génére bien g: subq $40, %rsp movq %rsp, %rdi call __gmpf_init movq %rsp, %rdi call __gmpf_clear xorl %eax, %eax addq $40, %rsp ret
Je ne sais pas si ca me servira mais je suis content d'y être arrivé smile
Détails sur la méthode d'implantation l'année prochaine devil
Si vous êtes sages (et êtes curieux de le savoir). wink

20

T'as jamais pensé à coder en C++, ou c'est vraiment pour le côté sympa du challenge ? cheeky

21

./9 si je ne m'abuse, ca va faire un appel a printer par argument a la macro PRINT non?
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.

22

./21: Oui

23

Donc ok c'est marrant mais question perf, c'est assez bof
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.

24

./23: Que ça prenne plus de place en RAM/code, je suis d'accord (et encore pas forcément, un bon compilateur devrait être capable d'optimiser tous ses appels à printf en un seul), mais question performance (selon mon expérience de quelqu'un qui a déjà écrit une fonction printf), ça sera à peine plus lent (juste le cout des appels de fonction en plus, vu que le cout de formatage sera le même)... Donc je ne comprends pas ta remarque.

25

Des nouvelles du front. J'écris désormais du code comme : // Définition d'une paire (string, mpz) STRUCT_DEF2(pair, (key, string_t, string_init, string_init_set, string_set, string_clear), (value, mpz_t, mpz_init, mpz_init_set, mpz_set, mpz_clear) ) // Définition d'une liste de paire LIST_DEF2(pair_t, pair, pair_init_set, pair_set, pair_clear) // Définition d'un tableau de liste. VECTOR_DEF2(list_pair_t, list_pair, list_pair_init, list_pair_init_copy, list_pair_copy, list_pair_clear) ... vector_list_pair_init(this->table); // Initialise le tableau table avec chaque élément une liste chainée composée de 2 éléments : une chaine de caractère de taille dynamique et un entier de taille variable vector_list_pair_set(this->table, org_table); // Copie les tableaux, en copiant chaque élément. et le tout, type-safe et sans aucun cast cheeky (Et c'est compatible avec la méthode décrite en ./19)

26

Bon, c'est certainement très puissant et ça aide sûrement à surmonter plein de problèmes, mais que ceux qui ne comprennent pas lèvent la main, parce que je me sens bien seul sad

27

C'est juste un exemple. En C++, ça donnerait (en remplaçant mpz par int) : #include <list> #include <utility> #include <vector> #include <string> typedef std::pair<std::string, int> my_pair; typedef std::list<my_pair> my_list; typedef std::vector<my_list> my_table; int f(my_table org) { my_table x; x = org; } Donc rien de bien sorcier ! grin

28

Sauf que la version C++ est lisible, alors que ton charabia en C… gni
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é

29

Si tu utilises la méthode ./19, cela devient quand même plus simple: STRUCT_DEF(pair, (key, string_t), (value, int) ) LIST_DEF(pair_t, pair) VECTOR_DEF(list_pair_t, list_pair) inf f(vector_list_pair_t org) { vector_list_pair_t x; INIT(x); SET(x, org_table); CLEAR(x); }

30

:x

Les macros c'est bien, mais ça devient excessif là, non?