summaryrefslogtreecommitdiff
path: root/article/leC.txt
blob: d66df0716a7a3d7d508628c6af768e0d4a170790 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
Les pratiques méconnues du C|12/04/12|svg|http://ache.nyan.at/perso/ache[200*200].svg
<div id="intro">Le C est un langage proche de la machine, on parle de langage bas-niveau. Conçu dans les années 70, initalement pour le système d'exploitation Unix. C'est désormais l'un des langages les plus popululaire malgrès son certain âge.</div>

<p>
  Le C est très complet et a énormément de subtilités, même après des années d'apprentissage et de pratique, la maîtrise totale de C langage n'est pas assurée. De plus, c'est un langage qui évolue, tous les 10 ans environ, la norme change, la dernière à ce jour est la norme C11, sortie en décembre dernier. Chaque norme apporte son lot de pratiques nouvelles et celle-ci ne sont pas toujours suivit ou enseignées. Même les normes nouvelles ne sont pas toujours suivit par les compilateurs. Pourtant, certaines pratiques permises par le langage C sont très utiles et méconnue.
Voyons rapidement quelques'une de ces pratiques.
</p>

<h3>Le C de base</h3>
<div id="intro">Depuis le C K&R, ces pratiques n'ont pas beaucoup évoluées mais sont pourtant méconues.</div>
<h4>L'Opérateur virgule</h4>

<p>  Très peu utilisé en pratique, mais peu s'avérer utile de temps à autre. La virgule est souvent utiliser pour constituer des listes de déclarations ou pour une liste de paramètre/argument à transmettre/récupérer à/par une fonction, mais ce n'est pas l'opérateur virgule. L'opérateur virgule lui permet d'associés 2 expressions. L'opérateur virgule s'entoure d'un couple d'expression, la première étant évalué comme de type void. Le résultat de l'opération est celui de la deuxième expression (même type donc).
Exemple d'utilisation :
  a = i*=5, b+5;
Comme l'opération se lit de droite à gauche, le première expression est i*=5 et la deuxième est b+5. À la fin de l'opération, la variable b n'est pas modifiée, a prend la valeur de b + 5 et i est égale à 5 fois sa valeur initiale. L'utilité de l'opérateur virgule peu semblé limité car on aurait put décomposer cette instruction en 2 :
  i *= 5;
  a = b + 5;
C'est pour cela que l'opérateur virgule n'est pas souvent utilisé. On la retrouve courrament cependant dans les for ou les conditions sur 2 lignes (afin de ne pas mettre de crochets).
  for(int i = 0; b >= i; --b, ++i);
  if( b == i)
    b = 0,
    i = 0;

Ne soyez pas surpris si vous en croisé dans un code ;) .
</p>

<h4>Les opérateurs # et ##</h4>

<p>  Le croisillon et le double croisillon sont 2 opérateurs de processeurs rarement utilisés. Pourtant leurs applications sont multiples. L'opérateur # tout d'abord permet de transformer son opérande en chaine de caractère, c'est pratique pour débugger par exemple.
  Exemple :
    #define WTF_WITH( x ) puts( #x " %i - %s", x, __LINE__ )
Comment ça marche ?
Avant la compilation, le préprocesseur transphorme WTF_WITH( var ) par printf( "var" " %i - " __LINE__ "\n", var).
Ici, on a 3 expressions littérales succéssives. Elles sont donc rassemblée en une "var %i - LaLigne\n".

   Maintenant, l'opérateur ## lui concatène 2 marqueurs de position. Pas très explicite voyons tout de suite en pratique :
   Exemple :
      #define WTF_WITH( x, y ) x ##y // equivalent à x ## y ou x##y
Ici, printf("%d", WTF_WITH( var, 2)); donnera après passage du préprocesseur, printf("%d", var2); . Là encore bien pratique pour le debuggage.

Seulement les possibilités de ces 2 opérateurs ne se limites pas au debuggage de code ....
</p>

<h4>Les unions</h4>
<p>
  Vous connaissez les structures ? Et bien les unions, c'est une structure donc vous ne pouvez utiliser que un seul des champs à la fois. L'utilité ?
  L'optimisation de la taille. En effet, la taille d'une union est égale à celle de son champ le plus lourd. Elle sert également à mieu organiser son code.
   union ID {
     char* name;
     char   ID;
   };
Ici, l'union ID fait sizeof(char*) bytes. On l'utilise comme une structure.
Les Unions sont utilisées par exemple par la SDL ...
</p>

<h3>Et depuis C89 et C99 ?</h3>
<p>
  Les normes C89 et C99 ont ajoutés beaucoup de nouveautés. Très peux sont courrament utilisées, et certaines ne sont carrément pas implémentées par les compilateurs. On peut pensée aux nombres complexes par exemple.
</p>
<h4>L'initialisation des tableaux</h4>
<p>
Depuis C89, on peut initialiser un tableau avec des crochets. Comme ceci :
 int tab[] = { [0] = 0, [1] = 1, [5] = 4};
 Ainsi, on peut initialiser le 1000ième éléments dès sa déclaration. 
 On peut également utiliser cette syntaxe afin de créer un tableau de associatif (ou de correspondance).
 C'est par exemple une méthode très pratique pour convertir une chaine en Base64.
</p>
<h4>L'initialisation des structures</h4>
<p>Personellement, j'ai du mal à voir l'utilité. Depuis C99, il est possible d'initiliser un structure champ par champ.
  struct coord pointA = {.x = 10, .y = 20};
</p>
<h3>Et depuis C11 ?</h3>

<h3>En matière d'obfuscation</h3>

<p>L'obsucation est le fait rendre un code illisible par un humain en complexifiant la lecture d'un code tout en  ...</p>

"Hj"[4];
Les Trigraphes
La conpressions des chaines littérales
assert()
sélection générique C11 http://www.siteduzero.com/forum-83-635220-p4-la-poo-et-le-c.html#r6283122
stdbool.h
stdint.h
Les composés litéraux