Ça manque d'informatique, dans le coin, vous ne trouvez pas ? :) Comme j'ai pris le soin de cultiver artistiquement les lecteurs geeks ces temps-ci, il est temps de cultiver geekement les amateurs d'art... Enfin, ça c'est la théorie, dans la pratique, je ne suis pas dupe non plus ;).
Commençons par des choses intéressantes : d'abord les classiques attributs en C pour gcc, que ceux qui connaissent trouvent banal (mes étudiants qui m'ont foutu la honte, y'avait une imprécision erratique sur mes slides >_< ), mais que bien des ingénieurs (et des chefs de projet) ne connaissent pas du tout (c'est la lose...). J'harangue tous mes lecteurs développeurs à apprendre aux moins les principaux attribute, qui servent tous les jours ou presque :
* "format" indique le style de format, on pourra trouver une utilisation dans KonQueR, où se trouve une fonction glprintf, qui marche comme printf mais en sur l'espace 3D (pour les menus par exemple), et qui nécessite donc plus de paramètres. C'est pourquoi le premier argument indique "à la printf" (ou autre, mais c'est le plus pratique), le second à partir de quel argument l'on doit considérer le même type de format, qui s'arrête au troisième précisé. Ça permet d'avoir des warnings quand on va faire une bêtise au niveau de la correspondance avec les %s, %i, etc. Super pratique.
extern int my_printf (void *my_object, const char *my_format, ...)
__attribute__ ((format (printf, 2, 3)));
* Mon préféré : packed. Il permet de minimiser l'espace mémoire requis, c'est-à-dire qu'il évite l'alignement (je n'ai jamais vu d'alignement sur 4 octets, mais cela dépend entièrement de l'architecture, et donc on peut en imaginer n'importe quel autre, mais plutôt dans les puissances de 2 a priori :) ). De base, lorsque l'on déclare une structure ou une union, le compilateur aligne effectivement les données de manière en optimiser l'accès en mémoire. Par exemple, sur x86, powerQUICC ou ARM, la structure suivante serait sur 8 octets et non 4 sans le "packing".
struct my_packed_struct __attribute__ ((__packed__))
{
char c;
int i;
};
L'avantage ensuite est de pouvoir manier ça avec une union :
union
{
struct my_packed_struct;
char table[5];
};
Ensuite, on peut faire des trucs funs
comme ça. Perso, j'utilise pour envoyer et recevoir sur le réseau, sans avoir à faire de casts atroces, et avec plus de flexibilité (ne pas forcément envoyer dans l'ordre ou en une seule fois, etc). Très pratique en fait pour matcher de la mémoire élégamment et remplir ses structures.
* Dans un genre similaire, l'attribut "aligned" permet de changer l'alignement, de le forcer sur une autre valeur ; moins utile, il faut bien avouer.
* Les autres à connaître (mais largement moins utilisés) : deprecated, unused, pure (attention ; moi j'aime po), ...
Ensuite, les trucs et astuces dans les instanciations (ouais, vocabulaire d'informaticien : initialisation, quoi) en C : designated inits. Cette fois-ci, c'est du standard, contrairement aux attributes et autres pragma ; en revanche, la compatibilité C/C++ n'est pas forcément de mise (le C++ n'est pas le C, de toute façon, on a beau le répéter, on trouve toujours de ces horreurs...). On connaît déjà bien en théorie les désignations par nom d'attributs d'une structure :
union foo { int i; double d; };
union foo f = { .d = 4 };
Mais ce qui est moins connu et qui poutre des mamans ours en slip, c'est l'initialisation des tableaux. Exemple :
int a[6] = { [4] = 29, [2] = 15, v3 };Ce qui nous donnera { 0, 0, 15, v3, 29, 0 } en deux coups de cuillère à pot. Déjà, rien qu'avec ça, on est assez ébahi : ça commence à ressembler à de l'Ada :p. Mais gcc implémente un truc complètement plus puissant (vraiment comme Ada) :
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };Ce qui troue l'anus. Fini les memset ou les horribles boucles for à chaud, qui initialisent au lancement de l'application en bouffant du CPU et du temps, alors que sacrédieu, on avait un tableau prédéfini à mettre dans le BSS (et parfois, quand on voulait absolument le mettre dans le rodata à coup de const, bien statique et intouchable, l'on voyait des gens s'échiner à écrire des milliers de valeurs dans un .h, et à la main, hein, pas avec un script tant qu'à faire :D ; pire encore, les "static" pour que tout soit garanti à 0 par défaut, oui oui, j'ai vu ça aussi...). Et puis, ce que je trouve super beau, c'est le mix des deux méthodes structure/tableau :
struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };Côté élégance, on retiendra ce qui suit, et qui peut marcher avec des enum :
int whitespace[256]
= { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };
Puisqu'on est en pure geekerie, j'indique ces deux pages web super intéressantes du même site : le mécanisme d'appel système sous Linux, et les vecteurs auxilières du format ELF, c'est court et très bon :).