star-style

Writing conventions for co-authors
Log | Files | Refs | README | LICENSE

star-c.7 (50995B)


      1 .\" Copyright (C) 2026 |Méso|Star> (contact@meso-star.com)
      2 .\"
      3 .\" Ce fichier fait partie de Star-Style.
      4 .\"
      5 .\" Star-Style est un logiciel libre ; vous pouvez le redistribuer ou le
      6 .\" modifier suivant les termes de la GNU General Public License telle
      7 .\" que publiée par la Free Software Foundation ; soit la version 3 de
      8 .\" la licence, soit (à votre gré) toute version ultérieure.
      9 .\"
     10 .\" Star-Style est distribué dans l'espoir qu'il sera utile, mais SANS
     11 .\" AUCUNE GARANTIE ; sans même la garantie tacite de QUALITÉ MARCHANDE
     12 .\" ou d'ADÉQUATION à UN BUT PARTICULIER. Consultez la GNU General
     13 .\" Public License pour plus de détails.
     14 .\"
     15 .\" Vous devez avoir reçu une copie de la GNU General Public License en
     16 .\" même temps que Star-Style ; si ce n'est pas le cas, consultez
     17 .\" <http://www.gnu.org/licenses>.
     18 .Dd July 13, 2026
     19 .Dt STAR-C 7
     20 .Os
     21 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
     22 .Sh NOM
     23 .Nm star-c
     24 .Nd guide d'écriture de code en C
     25 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
     26 .Sh DESCRIPTION
     27 Ce document décrit les conventions d'écriture des programmes C
     28 distribués par |Méso|Star>.
     29 Ces recommandations sont données à titre indicatif, et reste
     30 subordonnées aux pratiques effectivement retenues dans chaque
     31 projet ; le plus important étant d'en conserver la cohérence.
     32 Si bien que s'il appartient aux co-auteurs d'un projet de prendre
     33 certaines libertés quant à ce guide de style, toute participation à son
     34 développement devra alors s'efforcer de respecter le style d'écriture du
     35 projet, avant les préférences listées ici.
     36 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
     37 .Sh LE CONTENU D'UN PROJET
     38 En suivant le philosophie UNIX, assurer un jeu de
     39 fonctionnalités par programme aussi ramassé que possible de
     40 sorte à ce que sa mise en oeuvre et son interface restent
     41 simples et ciselées.
     42 L'objet étant d'assurer sa robustesse, son efficacité et sa
     43 modularité qui dépendent d'abord de sa
     44 .Em relation
     45 à un écosystème logiciel qui le dépasse, bien avant son catalogue de
     46 fonctionnalités ou ses prouesses de mise en oeuvre.
     47 .Pp
     48 Le périmètre étroit de chaque programme se retrouve dès lors dans la
     49 structure du projet auquel il appartient, dont le contenu est alors
     50 simple et peu hiérarchisé car comptant en définitive peu de fichiers.
     51 .Pp
     52 La structure type du répertoire d'un projet est :
     53 .Bd -literal -offset Ds
     54 README.md
     55 COPYING
     56 config.mk
     57 Makefile
     58 src/foo.h
     59 src/foo.c
     60 src/foo_bar.c
     61 doc/foo_bar.1
     62 doc/foo.3
     63 .Ed
     64 .Pp
     65 Avec :
     66 .Bl -dash -compact
     67 .It
     68 .Pa README.md
     69 le fichier qui donne le premier niveau d'informations sur le projet ;
     70 .It
     71 .Pa COPYING
     72 la license du projet qui liste ses conditions légales d'utilisation ;
     73 .It
     74 .Pa config.mk
     75 et
     76 .Pa Makefile
     77 les fichiers du système de génération automatique ;
     78 .It
     79 .Pa src/
     80 le répertoire qui contient les codes source du projet ;
     81 .It
     82 .Pa doc/
     83 le répertoire qui stocke sa documentation.
     84 .El
     85 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
     86 .Sh LE LANGAGE C
     87 Utiliser le langage
     88 .Em C89
     89 .Pq ANSI X3.159-1989
     90 aussi appelé C90
     91 .Pq ISO/IEC 9899:1990 ,
     92 les deux étant équivalent.
     93 .Pp
     94 Cette norme est plus épurée que celle qui lui succède à savoir le C99
     95 .Pq ISO SO/IEC 9899:1999 ,
     96 ce qui en fait un dialecte C à la fois plus simple, plus portable et
     97 plus consistant.
     98 Par exemple en ne proposant qu'une seule façon d'écrire les commentaires,
     99 et en interdisant de mélanger du code avec la définition de variables.
    100 .\""""""""""""""""""""""""""""""""""
    101 .Ss Le standard POSIX
    102 Ajouter le support du standard POSIX pour les seuls fichiers qui en ont
    103 besoin, pour notamment pouvoir utiliser des fonctions de la bibliothèque
    104 C standard sinon indisponibles via la seule norme du langage retenue.
    105 .Pp
    106 Pour ce faire, définir la macro
    107 .Sy _POSIX_C_SOURCE
    108 tout en haut du fichier C concerné, avant la moindre directive
    109 d'inclusion.
    110 Par exemple, pour utiliser le standard POSIX.1-2001 :
    111 .Bd -literal -offset Ds
    112 #define _POSIX_C_SOURCE 200112L
    113 .Ed
    114 .Pp
    115 Sous GNU/Linux, se référer à
    116 .Xr feature_test_macros 7
    117 pour une description exhaustive des macros utilisées pour activer le jeu
    118 de fonctionnalités d'un standard donné.
    119 .Pp
    120 L'utilisation d'un C enrichi du standard POSIX n'est ainsi utilisé que
    121 sur les seuls fichiers qui en explicite le besoin ; le C89 restant le
    122 langage utilisé partout ailleurs.
    123 Dans un même souci de portabilité, retenir la première version du
    124 standard POSIX à partir de laquelle la fonctionnalité recherchée est
    125 apparue.
    126 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    127 .Sh LA STRUCTURE D'UN FICHIER SOURCE
    128 Suivre une seule et même structure pour tous les fichiers
    129 sources, qu'ils soient des fichiers d'en-tête
    130 .Pq fichiers Ql *.h
    131 ou des unités de compilation
    132 .Pq fichiers Ql *.c .
    133 Un seul schéma de lecture participant à la clarté du code source.
    134 .Pp
    135 Ci-après sont listées les différentes parties d'un fichier source :
    136 .Bl -enum
    137 .\""""""""""""""""""""""""""""""""""
    138 .It
    139 Un commentaire avec l'avis de copyright et les avis de licence du
    140 programme
    141 .Pq section Sx L'AVIS DE COPYRIGHT ET LES AVIS DE LICENCE Ns
    142  ;
    143 .\""""""""""""""""""""""""""""""""""
    144 .It
    145 La définition d'une macro qui ajoute au langage C du fichier le support
    146 d'un standard POSIX
    147 .Pq section Sx LE LANGAGE C Ns
    148  ;
    149 .\""""""""""""""""""""""""""""""""""
    150 .It
    151 Pour un fichier d'en-tête, l'ouverture d'un garde-fou évitant sa double
    152 inclusion.
    153 Il est fermé en toute fin du fichier
    154 .Pq partie 10 Ns
    155  :
    156 .Bd -literal -offset Ds
    157 #ifndef FOO_H
    158 #define FOO_H
    159 .Ed
    160 .Pp
    161 Le nom de la macro testée puis définie est celui du fichier d'en-tête,
    162 suffixé par
    163 .Ql _H
    164 en référence à l'extension
    165 .Ql .h
    166 du fichier.
    167 Dans l'exemple qui précède, le garde-fou concerne donc le fichier
    168 .In foo.h .
    169 La convention de nommage est sinon celle utilisée pour n'importe quelle
    170 macro
    171 .Pq section Sx LE NOMMAGE .
    172 .\""""""""""""""""""""""""""""""""""
    173 .It
    174 L'inclusion des fichiers d'en-tête requis par le fichier source ;
    175 .Pq section Sx LES FICHIERS D'EN-TÊTE Ns
    176  ;
    177 .\""""""""""""""""""""""""""""""""""
    178 .It
    179 La définition des macros
    180 .Pq section Sx LES MACROS Ns
    181  ;
    182 .\""""""""""""""""""""""""""""""""""
    183 .It
    184 La déclaration anticipée des types structurés :
    185 .Bd -literal -offset Ds
    186 /* Type structurés externes au programme */
    187 struct plugh;
    188 struct quux;
    189 struct xyzzy;
    190 
    191 /* Types structurés définis ailleurs dans le programme */
    192 struct bar;
    193 struct foo;
    194 .Ed
    195 .\""""""""""""""""""""""""""""""""""
    196 .It
    197 La définition des constantes symboliques de type
    198 .Vt enum
    199 .Pq section Sx LES CONSTANTES SYMBOLIQUES Ns
    200  ;
    201 .\""""""""""""""""""""""""""""""""""
    202 .It
    203 La définition des types structurés et de leur(s) constante(s)
    204 .Pq section Sx LES STRUCTURES Ns
    205  ;
    206 .\""""""""""""""""""""""""""""""""""
    207 .It
    208 La déclaration et définition des fonctions
    209 .Pq section Sx LES FONCTIONS .
    210 Dans l'ordre qui suit :
    211 .Pp
    212 .Bl -tag -compact -width a.
    213 .It a.
    214 la déclaration des fonctions ;
    215 .It b.
    216 la définition des fonctions statiques ;
    217 .It c.
    218 pour les unités de compilation, la définition des fonctions.
    219 .El
    220 .\""""""""""""""""""""""""""""""""""
    221 .It
    222 Pour les fichiers d'en-tête, la fin du garde-fou ouvert en 3 pour éviter
    223 la double inclusion du contenu du fichier.
    224 .El
    225 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    226 .Sh LA LONGUEUR DES LIGNES
    227 La longueur maximale recommandée pour une ligne est de
    228 .Em 80
    229 caractères.
    230 .Pp
    231 Ce nombre, standardisé par les cartes perforées et les terminaux des
    232 années 1970, vise aussi à faciliter la lecture du code source en
    233 s'insipirant des conventions d'édition.
    234 Pour un texte imprimé avec une taille de police entre 9 à 12 points et
    235 un inter-ligne d'un caractère, un confort de lecture est assuré dès
    236 lors que chaque ligne compte entre 60 et 75 caractères.
    237 Une proximité avec les 80 caractères retenus, que l'indentation
    238 des sources vient encore renforcer.
    239 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    240 .Sh L'AVIS DE COPYRIGHT ET LES AVIS DE LICENCE
    241 Utiliser la licence libre GPLv3+ qui, en tant que licence copyleft,
    242 défend la copie, l'étude et la modification libres du programme ainsi
    243 licencié, et de ses évolutions.
    244 .Pp
    245 Ajouter une copie de la licence à la racine du projet, dans un fichier
    246 texte nommé
    247 .Pa COPYING
    248 .Pq voir Lk https://www.gnu.org/licenses/gpl-3.0.txt .
    249 .Pp
    250 Lister en commentaire l'avis de copyright et la déclaration
    251 d'autorisation de copie en en-tête de
    252 .Em chaque
    253 fichier source.
    254 .Pp
    255 Chaque copyright débute par le mot
    256 .Ql Copyright ,
    257 en anglais, suivi des 3 caractères
    258 .Ql (C) ,
    259 traduction ASCII du caractère © qui, quant à lui, peut ne pas être
    260 supporté par les jeu de caractères utilisé.
    261 Lister ensuite les années pour lesquelles une version du programme a été
    262 publiée, avant le nom de l'auteur(e) ayant participé(e) à
    263 sa réalisation.
    264 Conclure chaque avis par l'adresse de contact de l'auteur(e), donnée
    265 entre parenthèses.
    266 .Pp
    267 Sauter une ligne après l'avis de copyright et ajouter la déclaration
    268 autorisant la copie telle que donnée par la Fondation pour le logiciel
    269 libre.
    270 Utiliser l'avis de copyright en anglais qui, au contraire de sa
    271 traduction française, revêt une signification juridique.
    272 .Pp
    273 L'en-tête type d'un fichier source du programme
    274 .Ql Foo
    275 est :
    276 .Bd -literal -offset Ds
    277 /* Copyright (C) 2016-2018, 2020, 2022, 2026
    278  *   Jeanne Lambda (jeanne.lambda@courriel.fr)
    279  * Copyright (C) 2017, 2019 Jean Untel (juntel@courriel.fr)
    280  * Copyright (C) 2024 |Méso|Star> (contact@meso-star.com)
    281  *
    282  * This file is part of Foo.
    283  *
    284  * Foo is free software: you can redistribute it and/or
    285  * modify it under the terms of the GNU General Public License
    286  * as published by the Free Software Foundation, either
    287  * version 3 of the License, or (at your option) any later
    288  * version.
    289  *
    290  * Foo is distributed in the hope that it will be useful,
    291  * but WITHOUT ANY WARRANTY; without even the implied warranty
    292  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
    293  * the GNU General Public License for more details.
    294  *
    295  * You should have received a copy of the GNU General Public
    296  * License along with Foo. If not, see
    297  * <https://www.gnu.org/licenses/>. */
    298 .Ed
    299 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    300 .Sh L'INDENTATION
    301 Indenter le texte par 2 espaces.
    302 La mise en page du texte, taille de ligne comprise, est ce faisant
    303 indépendante de la taille d'une tabulation.
    304 .Pp
    305 Les auteurs sont encouragés à configurer leur éditeur pour
    306 qu'il développe chaque caractère tabulation en 2 espaces
    307 .Pq section Sx FICHIERS .
    308 Et ainsi continuer à utiliser la touche tabulation pour l'indentation.
    309 .Pp
    310 Limiter l'indentation à 2 caractères, contre 8 pour le standard de facto
    311 des tabulations, laisse plus d'espace aux différents niveaux
    312 d'indentation, dès lors moins contraints par la limite du nombre de
    313 caractères par ligne
    314 .Pq section Sx LA LONGUEUR DES LIGNES .
    315 Néanmoins, un niveau d'indentation supérieur à 3 est aussi le signe d'un
    316 déficit de structure dans l'écriture du programme.
    317 Les 2 espaces retenus pour indenter le code n'est donc pas une
    318 incitation à aller au delà de 3 niveaux d'indentation sous prétexte de
    319 disposer de plus d'espace par niveau.
    320 .Pp
    321 Indenter le contenu de chaque bloc
    322 .Pq section Sx LES BLOCS .
    323 Pour la directive
    324 .Ql switch ,
    325 indenter chaque
    326 .Ql case
    327 ainsi que leur contenu :
    328 .Bd -literal -offset Ds
    329 switch (opt) {
    330   case 'e':
    331     errno = 0;
    332     epsilon = strtod(optarg, NULL);
    333     if (errno != 0) err = 1;
    334     break;
    335   case 'h':
    336     printf("usage: foo [-hov]\en");
    337     break;
    338   case 'o':
    339     output = optarg;
    340     break;
    341   case 'v':
    342     verbose += (verbose < 3);
    343     break;
    344   default:
    345     err = 1;
    346     break;
    347 }
    348 .Ed
    349 .Pp
    350 Motiver l'utilisation de plusieurs instructions par ligne par
    351 l'expressivité du code en résultant, qu'une écriture resserrée viendrait
    352 renforcer :
    353 .Bd -literal -offset Ds
    354 if (x == NULL || y == NULL) { err = 1; goto error; }
    355 x[0] = 1.0; x[1] = 0.0;
    356 y[0] = 0.0; y[1] = 1.0;
    357 .Ed
    358 .Pp
    359 Ne sauter au plus qu'une ligne.
    360 Ne pas laisser d'espace en fin de ligne et supprimer les lignes vides
    361 en fin de fichier.
    362 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    363 .Sh LES COMMENTAIRES
    364 Utiliser des commentaires dès lors que la seule expressivité serrée du
    365 code ne permet pas d'exprimer l'entièreté du discours que les sources
    366 doivent rendre compte, ou la logique qu'il met effectivement en oeuvre.
    367 .Pp
    368 Ajouter un espace après l'ouverture du commentaire
    369 .Ql /*
    370 et avant sa fermeture
    371 .Ql */ .
    372 .Pp
    373 Si un commentaire occupe plusieurs lignes, ajouter un caractère
    374 .Ql *
    375 en début de ligne, aligné avec le caractère
    376 .Ql *
    377 de la ligne qui précède.
    378 Ajouter un espace entre le caractère
    379 .Ql * ,
    380 qui marque la continuation du commentaire, et la suite du commentaire :
    381 .Bd -literal -offset Ds
    382 /* Valeurs de hachage initiales, à savoir les 32 premiers bits
    383  * de la partie fractionnaire des racines carrées des 4 premiers
    384  * nombres premiers (2, 3, 5 et 7) */
    385 state[0] = 0x6a09e667;
    386 state[1] = 0xbb67ae85;
    387 state[2] = 0x3c6ef372;
    388 state[3] = 0xa54ff53a;
    389 .Ed
    390 .Pp
    391 Les commentaires servent aussi à structurer la lecture du code source.
    392 Que ce soit à l'échelle des instructions, par un commentaire
    393 .Dq chapeau
    394 qui résume la séquence de code qui suit :
    395 .Bd -literal -offset Ds
    396 /* Enregistrer le résultat */
    397 ((uint32_t*)hash)[0] = big_endian_32(state[0]);
    398 ((uint32_t*)hash)[1] = big_endian_32(state[1]);
    399 ((uint32_t*)hash)[2] = big_endian_32(state[2]);
    400 ((uint32_t*)hash)[3] = big_endian_32(state[3]);
    401 .Ed
    402 .Pp
    403 ou à l'échelle du fichier, où les commentaires servent alors de
    404 séparateur entre ses différentes sections
    405 .Pq voir Sx LA STRUCTURE D'UN FICHIER SOURCE .
    406 Dans ce cas, encadrer le commentaire par deux ligne de caractères
    407 .Ql *
    408 qui débute ou se termine par le caractère
    409 .Ql /
    410 si, respectivement, la ligne précède ou suit l'intitulé de la section :
    411 .Bd -literal -offset Ds
    412 /***********************************************************
    413  * Définition des fonctions utilitaires
    414  **********************************************************/
    415 static void
    416 foo(uint32_t bar[4], const char baz[64])
    417 {
    418   ...
    419 }
    420 .Ed
    421 .Pp
    422 À noter que dans l'exemple qui précède, la taille des lignes
    423 d'encadrement est limitée par des contraintes d'édition de la présente
    424 page de manuel.
    425 Dans un fichier source, étendre ces lignes pour qu'elles occupent la
    426 longueur maximale recommandée pour une ligne
    427 .Pq section Sx LA LONGUEUR DES LIGNES .
    428 .Pp
    429 Pour expliciter le contexte général d'un fichier, en terme d'utilisation
    430 ou d'architecture logicielle, insérer un commentaire en en-tête du
    431 fichier en laissant les caractères d'ouverture ou de fermeture de
    432 commentaires sur une ligne séparée :
    433 .Bd -literal -offset Ds
    434 /*
    435  * Interface de programmation des tableaux extensibles.
    436  * Cette structure de données peut être utilisée avec des
    437  * types de données qui ne nécessitent pas de processus
    438  * d'initialisation ou de libération et qui peuvent être
    439  * copiés bit à bit
    440  */
    441 .Ed
    442 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    443 .Sh LES FICHIERS D'EN-TÊTE
    444 Inclure les fichiers d'en-tête dans l'ordre qui suit :
    445 .Bl -enum -compact
    446 .It
    447 les en-têtes locaux au programme ;
    448 .It
    449 les en-têtes des dépendances du programme ;
    450 .It
    451 les en-têtes systèmes et ceux de la bibliothèque C standard.
    452 .El
    453 .Pp
    454 Les fichiers d'en-tête sont ainsi inclus dans l'ordre décroissant de
    455 leur niveau d'abstraction.
    456 Cet ordre participe à garantir que chaque fichier d'en-tête inclus les
    457 en-têtes dont il a lui même besoin, indépendamment des directives
    458 d'inclusion qui précèdent sa propre inclusion.
    459 Si ce n'est pas le cas, la compilation pourra échouer, symptôme qu'un
    460 des fichiers d'en-tête n'est pas auto-consistant.
    461 .Pp
    462 Dans chaque groupe, trier les directives d'inclusion par ordre
    463 alphabétique des fichiers d'en-tête.
    464 Si besoin, ajouter un commentaire court, sur la même ligne que la
    465 directive d'inclusion, qui explicite la raison pour laquelle la fichier
    466 est inclus.
    467 .Bd -literal -offset Ds
    468 #include "bar.h"
    469 #include "foo.h"
    470 #include "qux.h"
    471 
    472 #include <baz.h>
    473 
    474 #include <float.h> /* FLT_MAX */
    475 #include <stdio.h>
    476 .Ed
    477 .Pp
    478 S'efforcer de n'inclure que les seuls fichiers d'en-tête
    479 réellement nécessaires au fichier ;
    480 par exemple par une déclaration anticipée des types structurés à
    481 la place d'inclure des en-têtes dans le seul but de déclarer lesdits
    482 types.
    483 Un enjeu a considérer avec d'autant plus d'attention que le fichier
    484 concerné par les inclusions est lui même un fichier d'en-tête, par
    485 conséquent amené à être lui même inclus.
    486 L'objet étant de limiter autant que possible le nombre de fichiers
    487 inclus par unité de compilation, pour limiter les accès disque et ainsi
    488 réduire les temps de compilation.
    489 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    490 .Sh LA VISIBILITÉ DES SYMBOLES
    491 Par défaut, n'exposer aucun symbole
    492 .Po
    493 option
    494 .Fl fvisibility=hidden
    495 du compilateur
    496 .Xr gcc 1
    497 .Pc ,
    498 à l'exception de ceux de l'interface de programmation d'une
    499 bibliothèque.
    500 .\""""""""""""""""""""""""""""""""""
    501 .Ss Les symboles d'interface
    502 Privilégier l'écriture d'un seul fichier d'en-tête pour exposer
    503 l'interface de programmation d'une bibliothèque.
    504 Y définir une macro qui exporte les symboles qu'elle déclare dès lors
    505 que ce fichier d'en-tête est inclus par une unité de compilation de la
    506 bibliothèque.
    507 Et qui se contente d'importer ces mêmes symboles si ce même fichier est
    508 inclus par un programme tiers :
    509 .Bd -literal -offset Ds
    510 #include <rsys/rsys.h>
    511 
    512 #if defined(FOO_SHARED_BUILD)
    513   #define FOO_API extern EXPORT_SYM
    514 else
    515   #define FOO_API extern IMPORT_SYM
    516 #endif
    517 .Ed
    518 .Pp
    519 Avec :
    520 .Bl -dash -compact
    521 .It
    522 .Sy FOO_SHARED_BUILD
    523 une macro définie uniquement à la compilation de la bibliothèque
    524 .Po
    525 option
    526 .Fl DFOO_SHARED_BUILD
    527 du compilateur C
    528 .Pc Ns
    529  ;
    530 .It
    531 .Sy EXPORT_SYM
    532 et
    533 .Sy IMPORT_SYM
    534 des directives définies dans la bibliothèque
    535 .Ql RSys .
    536 Elles enrichissent le langage C d'une gestion explicite de la visibilité
    537 des symboles.
    538 .El
    539 .Pp
    540 Utiliser cette macro à la déclaration des variables et constantes
    541 d'interfaces :
    542 .Bd -literal -offset Ds
    543 /* Variables globales de l'interface de programmation */
    544 FOO_API const struct foo foo_plugh;
    545 FOO_API const struct foo foo_xyzzy;
    546 .Ed
    547 .Pp
    548 Déclarer le prototype des fonctions d'interface entre les directives
    549 .Sy BEGIN_DECLS
    550 et
    551 .Sy END_DECLS ,
    552 elles aussi définies dans la bibliothèque
    553 .Ql RSys
    554 .Pq en-tête In rsys/rsys.h .
    555 Ainsi, le fichier d'en-tête peut être inclus par un programe C++ :
    556 .Bd -literal -offset Ds
    557 BEGIN_DECLS
    558 
    559 FOO_API void
    560 foo_bar
    561   (int i,
    562    int* j);
    563 
    564 FOO_API int
    565 foo_qux
    566   (double d,
    567    int i);
    568 
    569 END_DECLS
    570 .Ed
    571 .\""""""""""""""""""""""""""""""""""
    572 .Ss Les symboles internes partagés
    573 Pour les fichiers d'en-tête internes au programme, utiliser la directive
    574 .Sy LOCAL_SYM ,
    575 définie dans le fichier
    576 .In rsys/rsys.h
    577 de la bibliothèque
    578 .Ql RSys ,
    579 pour déclarer les variables globales et prototypes de fonctions.
    580 Ainsi leur symbole n'est pas exposé à l'extérieur du programme.
    581 .Bd -literal -offset Ds
    582 #include <rsys/rsys.h>
    583 
    584 extern LOCAL_SYM char bar[128];
    585 
    586 extern LOCAL_SYM void
    587 quux
    588   (char* tab,
    589    size_t length);
    590 .Ed
    591 .Pp
    592 Cette directive est redondante si le compilateur est configuré pour
    593 masquer par défaut tous les symboles
    594 .Po
    595 option
    596 .Fl fvisibility=hidden
    597 de
    598 .Xr gcc 1
    599 .Pc .
    600 Utiliser
    601 .Sy LOCAL_SYM
    602 permet néanmoins de s'exonérer de cet a priori, tout en uniformisant
    603 les déclarations des fonctions et variables en explicitant pour chaque
    604 déclaration la visibilité du symbole associé.
    605 .\""""""""""""""""""""""""""""""""""
    606 .Ss Les symboles internes à une unité de compilation
    607 Utiliser le mot clé
    608 .Ql static
    609 pour déclarer des variables, constantes, et fonctions visibles
    610 uniquement au sein d'une unité de compilation.
    611 .Pp
    612 C'est notamment le cas des constantes symboliques structurées :
    613 .Bd -literal -offset Ds
    614 struct foo {
    615   int bar;
    616   int qux;
    617 };
    618 static const struct foo FOO_DEFAULT = {1, 0};
    619 .Ed
    620 .Pp
    621 Mais aussi des fonctions utilitaires, qu'elles soient
    622 propres à un fichier C, ou définies dans un fichier d'en-tête.
    623 .Bd -literal -offset Ds
    624 static void
    625 hello(void)
    626 {
    627   printf("Hello, world!\en");
    628 }
    629 .Ed
    630 .Pp
    631 Ces fonctions peuvent en plus être déclarées avec la directive
    632 .Sy INLINE ,
    633 définie dans l'en-tête
    634 .In rsys/rsys.h
    635 de la bibliothèque
    636 .Ql RSys ,
    637 pour suggérer au compilateur de substituer l'appel de la fonction par le
    638 corps de celle-ci, de sorte à éviter le surcoût de l'appel.
    639 Cette directive est équivalente au mot clé
    640 .Ql inline
    641 du C99, indisponible dans le dialecte C retenu
    642 .Pq section Sx LE LANGAGE C .
    643 .Bd -literal -offset Ds
    644 static INLINE void
    645 foo(void)
    646 {
    647   printf("bar\en");
    648 }
    649 .Ed
    650 .Pp
    651 Limiter la directive
    652 .Sy INLINE
    653 aux fonctions élémentaires, destinées à être appelées fréquemment et
    654 dont le coût de l'appel pourrait alors s'avérer significatif.
    655 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    656 .Sh LES BLOCS
    657 Ouvrir chaque bloc sur la même ligne que la directive qui en est à
    658 l'origine
    659 .Po
    660 .Ql do ,
    661 .Ql enum
    662 .Ql for ,
    663 .Ql if ,
    664 .Ql struct ,
    665 .Ql switch ,
    666 .Ql union ,
    667 .Ql while
    668 .Pc ,
    669 en séparant par un espace la fin de la directive et le caractère
    670 .Ql {
    671 qui marque l'ouverture du bloc :
    672 .Bd -literal -offset Ds
    673 if (foo) {
    674   bar();
    675   qux();
    676 }
    677 .Ed
    678 .Pp
    679 Exception faite des fonctions, ou le bloc associé est ouvert sur la
    680 ligne qui suit :
    681 .Bd -literal -offset Ds
    682 static void
    683 foo(void)
    684 {
    685   printf("bar\en");
    686 }
    687 .Ed
    688 .Pp
    689 Fermer un bloc sur une ligne à part sauf s'il est suivi d'une nouvelle
    690 structure de contrôle associée à la précédente
    691 .Po
    692 .Ql if else ,
    693 .Ql do while
    694 .Pc .
    695 Dans ce cas, ajouter la nouvelle instruction sur la même ligne que celle
    696 utilisée pour fermer le bloc, en la séparant du caractère
    697 .Ql }
    698 par un espace.
    699 .Pp
    700 Aligner la fermeture du bloc à l'indentation de sa directive, ou, dans
    701 le cas de directives qui se suivent, à l'indentation de la première
    702 directive à l'origine des blocs successifs :
    703 .Bd -literal -offset Ds
    704 if (foo) {
    705   bar();
    706 } else {
    707   qux();
    708 }
    709 .Ed
    710 .Pp
    711 Écrire sur une seule ligne une directive et les opérations qu'elle
    712 contrôle que si la clarté du code n'en est pas impactée.
    713 Dans ce cas, l'ouverture et la fermeture du bloc associé se fait sur une
    714 seule et même ligne :
    715 .Bd -literal -offset Ds
    716 if (foo) { bar(); return 0; }
    717 .Ed
    718 .Pp
    719 Ne pas utiliser d'accolades si la structure de contrôle n'est suivie
    720 d'aucune ou d'une seule directive écrite sur la même ligne :
    721 .Bd -literal -offset Ds
    722 while (foo());
    723 
    724 if (bar) return 0;
    725 .Ed
    726 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    727 .Sh LES MOTS CLÉS
    728 Ajouter un espace après chaque structure de contrôle
    729 .Ql if ,
    730 .Ql switch ,
    731 .Ql for
    732 et
    733 .Ql while
    734 pour les différencier des appels de fonctions.
    735 Ne pas ajouter d'espace après l'ouverture et avant la fermeture des
    736 parenthèses qui détourent leur(s) expression(s) :
    737 .Bd -literal -offset Ds
    738 if (i < 10) {
    739   foo(i);
    740 }
    741 .Ed
    742 .Pp
    743 Ajouter un espace après chaque point virgule qui sépare les expressions
    744 d'une boucle
    745 .Ql for
    746 sauf si l'expression qui suit est vide :
    747 .Bd -literal -offset Ds
    748 for (i=0; i<10; foo(i++));
    749 
    750 for (;;) { /* Boucle infinie */
    751   poll();
    752   if(bar) break;
    753 }
    754 .Ed
    755 .Pp
    756 Assimiler l'instruction
    757 .Ql sizeof
    758 à une fonction ; ne pas insérer d'espace entre le mot clé et son
    759 expression entourée de parenthèses :
    760 .Bd -literal -offset Ds
    761 sz = sizeof(int);
    762 .Ed
    763 .\""""""""""""""""""""""""""""""""""
    764 .Ss L'instruction Ql switch
    765 Limiter à quelques lignes le contenu de chaque
    766 .Ql case
    767 d'une instruction
    768 .Ql switch ,
    769 celle-ci devant donner à lire la seule répartition des traitements,
    770 fonction de la valeur que peut prendre l'expression du
    771 .Ql switch .
    772 Et non les traitements eux même, sauf s'ils sont triviaux.
    773 Un
    774 .Ql case
    775 au contenu trop fourni est alors le signe d'un manque de structure dans
    776 l'écriture du programme.
    777 .Pp
    778 Toujours ajouter une instruction
    779 .Ql default
    780 même si l'ensemble des valeurs que pourraient prendre l'expression du
    781 .Ql switch
    782 est censé être couvert par les différents
    783 .Ql case .
    784 C'est notamment le cas quand l'expression est une variable
    785 d'énumération.
    786 Utiliser alors la directive
    787 .Sy FATAL ,
    788 définie par la bibliothèque
    789 .Ql RSys
    790 .Pq en-tête In rsys/rsys.h ,
    791 pour signifier un comportement inattendu.
    792 Et ainsi pouvoir diagnostiquer une erreur dans la valeur de l'expression
    793 du
    794 .Ql switch ,
    795 ou un
    796 .Ql case
    797 manquant :
    798 .Bd -literal -offset Ds
    799 switch (i) {
    800   case FOO: foo(); break;
    801   case BAR: bar(); break;
    802   case QUX: qux = 1; break;
    803   default: FATAL("Unreachable code\en"); break;
    804 }
    805 .Ed
    806 .Pp
    807 Ajouter la directive
    808 .Sy FALLTHROUGH ,
    809 définie dans le fichier d'en-tête
    810 .In rsys/rsys.h
    811 de la bibliothèque
    812 .Ql RSys ,
    813 en fin des instructions
    814 .Ql case
    815 qui s'enchaînent.
    816 L'ajout de cette directive permet d'expliciter que c'est bien le
    817 comportement attendu et non l'oublie d'une instruction
    818 .Ql break ,
    819 en plus d'éviter un possible message d'avertissement à la compilation
    820 .Pq option Fl Wimplicit-fallthrough No de Xr gcc 1 Ns
    821  :
    822 .Bd -literal -offset Ds
    823 switch (c) {
    824   case 'a':
    825     foo = 1;
    826     FALLTHROUGH;
    827   case 'b':
    828     bar = 1;
    829     break;
    830   default:
    831     usage();
    832     break;
    833 }
    834 .Ed
    835 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    836 .Sh LE NOMMAGE
    837 .\""""""""""""""""""""""""""""""""""
    838 .Ss Les variables
    839 Nommer les variables en minuscules.
    840 Utiliser le tiret bas
    841 .Ql _
    842 au titre de séparateur entre les termes utilisés dans le nom des
    843 variables :
    844 .Bd -literal -offset Ds
    845 foo_bar
    846 .Ed
    847 .Pp
    848 Expliciter l'objet d'une variable dans son nom avec d'autant plus de
    849 précision que sa portée est grande.
    850 Une variable locale à un bloc de quelques lignes pourra se contenter
    851 d'un nom abrégé tel que
    852 .Va tmp
    853 pour un résultat temporaire, voire n'être qu'un seul caractère
    854 pour un indice
    855 .Va i
    856 ou un nombre d'éléments
    857 .Va n Ns
    858  ; leur contexte d'utilisation venant préciser ce que leur nom résume.
    859 Ce nom abrégé vient non seulement alléger l'écriture mais aussi en
    860 renforcer l'expressivité.
    861 Par exemple
    862 .Va tableau Ns Bq Va i
    863 reste plus clair que
    864 .Va tableau Ns Bq Va indice .
    865 .Pp
    866 Les variables globales sont au contraire à nommer de sorte à décrire ce
    867 qu'elles représentent, indépendamment de tout contexte d'utilisation,
    868 par construction distant de leur déclaration.
    869 Un compteur d'allocations global à un programme aura donc pour nom
    870 .Va compteur_allocations
    871 plutôt que
    872 .Va cpt_allocs .
    873 .Pp
    874 Pour une variable globale déclarée au niveau de l'interface d'une
    875 bibliothèque, préfixer ladite variable avec l'acronyme de la
    876 bibliothèque.
    877 Un compteur d'allocation global à la bibliothèque
    878 .Ql Foo ,
    879 et déclaré en tant que variable globale de son interface, sera alors
    880 nommé
    881 .Va foo_compteur_allocations .
    882 .\""""""""""""""""""""""""""""""""""
    883 .Ss Les fonctions
    884 Nommer les fonctions avec des caractères alphanumérique en minuscules,
    885 et séparer les termes qui composent leur nom par un tiret bas
    886 .Pq caractère Ql _ .
    887 .Pp
    888 Donner à une fonction un nom d'autant plus explicite que sa portée est
    889 importante.
    890 Une fonction utilitaire pourra se contenter d'un nom abrégé, tel que
    891 .Fn cmp
    892 pour une fonction de comparaison utilisée comme argument d'un appel à
    893 .Xr qsort 3
    894 au sein d'un fichier C.
    895 Là où une fonction partagée entre plusieurs unités de compilation aura
    896 un nom plus expressif, tel que
    897 .Fn compare_bar ,
    898 pour notamment expliciter le type
    899 .Vt struct bar
    900 des variables comparées.
    901 Jusqu'à préfixer le nom de la fonction par l'acronyme de la bibliothèque
    902 quand elle est une fonction d'interface de ladite bibliothèque.
    903 Pour la bibliothèque
    904 .Ql Foo ,
    905 une fonction d'interface sera alors nommée
    906 .Fn foo_compare_bar .
    907 .\""""""""""""""""""""""""""""""""""
    908 .Ss Les déclarations de types
    909 Utiliser des caractères alphanumériques en minuscules pour nommer les
    910 structures, unions et énumérations.
    911 Utiliser le tiret bas
    912 .Ql _
    913 pour séparer les différents termes qui composent leur nom.
    914 .Bd -literal -offset Ds
    915 struct foo {
    916   int bar;
    917   int baz
    918 };
    919 
    920 union foo_bar {
    921   double qux;
    922   int xyzzy;
    923 };
    924 .Ed
    925 .Pp
    926 Utiliser la même convention pour nommer les déclarations typedef.
    927 À l'exception du suffixe
    928 .Ql _T
    929 ajouté au nom de l'identificateur du type, en écho au suffixe
    930 .Ql _t
    931 souvent utilisé pour ce type de déclaration, mais réservé par le
    932 standard POSIX.
    933 .Bd -literal -offset Ds
    934 typedef int foo_T;
    935 typedef char foo_bar_T[256];
    936 .Ed
    937 .Pp
    938 Ne pas utiliser de déclaration typedef sur les structures, unions et
    939 énumérations de sorte à permettre leur déclaration anticipée.
    940 .Pp
    941 Préfixer le nom d'un type par l'acronyme de la bibliothèque dès lors
    942 qu'il est un type déclaré en tant que type de son interface.
    943 Par exemple, un type structuré de l'interface de la bibliothèque
    944 .Ql Foo
    945 sera nommé
    946 .Vt struct foo_mon_type .
    947 .\""""""""""""""""""""""""""""""""""
    948 .Ss Constantes et macros
    949 Utiliser des majuscules pour nommer les constantes symboliques, qu'elles
    950 soient des macros, des constantes énumérées, ou des variables déclarées
    951 comme constantes.
    952 Séparer par un tiret bas
    953 .Ql _
    954 les termes qui composent leur nom :
    955 .Bd -literal -offset Ds
    956 #define FOO_BAR 42
    957 
    958 enum foo {
    959   BAR_BAZ,
    960   QUX
    961 };
    962 
    963 static const enum foo FOO_XYZZY = BAR_BAZ;
    964 .Ed
    965 .Pp
    966 Nommer une constante ou une macro de manière d'autant plus explicite
    967 que sa portée est importante.
    968 Une constante définie localement à une fonction pourra se contenter
    969 d'un nom abrégé, jusqu'à n'être qu'un seul caractère, par exemple pour
    970 un nombre d'éléments constant
    971 .Sy N .
    972 Là où le nom d'une macro ou d'une constante définie dans un fichier
    973 d'en-tête se devra d'être plus explicite, tel que
    974 .Sy NOMBRE_ELEMENTS_MAX .
    975 Et être préfixée par l'acronyme de la bibliothèque si elle est déclarée
    976 comme macro ou constante de son interface.
    977 Par exemple, pour la bibliothèque
    978 .Ql Foo ,
    979 .Sy FOO_NOMBRE_ELEMENTS_MAX .
    980 .Pp
    981 Utiliser la convention typographique dite
    982 .Dq camel case
    983 pour nommer les arguments des macros ;
    984 les termes qui composent leur nom sont séparés par une variation de la
    985 casse typographique.
    986 Un terme débute par une majuscule, suivi de caractères
    987 alphanumériques en minuscule.
    988 .Bd -literal -offset Ds
    989 #define FOO_BAR(FooBar, Qux) ((FooBar) + (Qux))
    990 .Ed
    991 .Pp
    992 Ainsi, les arguments de macros sont différenciés des constantes
    993 symboliques et des variables.
    994 .Pp
    995 À noter que la macro elle même est nommée selon la même convention que
    996 celle utilisée pour les constante symboliques
    997 .Pq en majuscule et un tiret bas pour séparer ses différents termes .
    998 La parenthèse ouvrante, collée au nom de la macro, permettant de
    999 différencier les 2 cas.
   1000 .\""""""""""""""""""""""""""""""""""
   1001 .Ss Les variables et macros internes
   1002 Suffixer par deux tirets bas
   1003 .Ql __
   1004 les variables membres d'une structure définie publiquement, qui n'ont
   1005 cependant une signification qu'en interne des fonctions d'interface de
   1006 la structure.
   1007 L'enjeu étant de souligner que ces variables ne sont accessibles que par
   1008 effet de bord, et ne s'addressent
   1009 .Em pas
   1010 aux utilisatrices et utilisateurs, qui ne devraient donc pas y accéder
   1011 directement :
   1012 .Bd -literal -offset Ds
   1013 struct foo {
   1014   double bar;
   1015   int baz;
   1016   int* qux__; /* Variable interne */
   1017 };
   1018 .Ed
   1019 .Pp
   1020 Utiliser le même suffixe en double tirets bas
   1021 .Ql __
   1022 pour nommer les variables internes à une macro, afin d'éviter de masquer
   1023 les variables définies dans le contexte où la macro est développée :
   1024 .Bd -literal -offset Ds
   1025 #define FOO(Bar, N) {                                      \e
   1026   int i__;                                                 \e
   1027   for (i__ = 0; i__ < N; Bar(i__), ++i__);                 \e
   1028 } (void)0
   1029 .Ed
   1030 .Pp
   1031 Suffixer les macros d'un fichier d'en-tête par deux tirets bas
   1032 .Ql __
   1033 dès lors qu'elles sont propres au fichier d'en-tête, et donc
   1034 vraisemblablement inacessibles au delà :
   1035 .Bd -literal -offset Ds
   1036 #define FOO__(Type, Dim)                                   \e
   1037   struct Type {                                            \e
   1038     int i[Dim];                                            \e
   1039     float f[Dim];                                          \e
   1040   }
   1041 FOO__(bar, 2);
   1042 FOO__(baz, 3);
   1043 FOO__(qux, 4);
   1044 #undef FOO__
   1045 .Ed
   1046 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1047 .Sh LES FONCTIONS
   1048 S'attacher à ce que chaque fonction reste simple et concise, en ne
   1049 s'appliquant à ne lui faire faire qu'une seule chose.
   1050 Ce faisant, le corps d'une fonction devrait être lisible sur un ou deux
   1051 écran, avec comme référence la taille des terminaux telle que
   1052 démocratisée à la fin des années 1970, à savoir 24 lignes.
   1053 .Pp
   1054 Un indice quant à la taille qu'une fonction devrait s'efforcer à avoir
   1055 est donné par ses niveaux d'indentation.
   1056 Plus elle compte de niveaux et plus elle devrait être ramassée.
   1057 De même, un nombre de variables locales supérieur à dix peut être le
   1058 signe d'une fonction trop dense.
   1059 .Pp
   1060 Écrire les directives qui contrôlent la portée d'une fonction et son
   1061 type de retour sur une ligne séparée de son nom.
   1062 L'expression régulière
   1063 .Ql ^nom_de_fonction
   1064 peut ainsi être utilisée pour la recherche d'une fonction dans les
   1065 différents fichiers sources.
   1066 .Pp
   1067 Pour une déclaration, revenir à la ligne avant d'ouvrir la parenthèse de
   1068 la fonction, précédée d'une indentation par rapport au nom de la
   1069 fonction sur la ligne qui précède.
   1070 Puis, lister les arguments de la fonction, en revenant à la ligne après
   1071 chacun d'eux et en les alignant les uns par rapport aux autres.
   1072 Ajouter la parenthèse fermante
   1073 .Ql \&)
   1074 et le point virgule
   1075 .Ql \&;
   1076 sur la ligne du dernier argument, sans espace supplémentaire :
   1077 .Bd -literal -offset Ds
   1078 extern LOCAL_SYM void
   1079 foo_bar
   1080   (struct foo* foo,
   1081    const int qux,
   1082    const float xyzzy);
   1083 .Ed
   1084 .Pp
   1085 Les différentes parties qui composent le profil de la fonction sont
   1086 ainsi identifiables par la seule mise en page de sa déclaration.
   1087 .Pp
   1088 Lors de sa définition, lister les arguments de la fonction sur la même
   1089 ligne que le nom de la fonction, sans ajouter d'espace entre le nom de
   1090 la fonction et sa parenthèse ouvrante.
   1091 Si la liste des arguments dépasse la longueur maximale d'une ligne
   1092 .Pq section Sx LA LONGUEUR DES LIGNES
   1093 lister les arguments comme pour une déclaration :
   1094 .Bd -literal -offset Ds
   1095 void
   1096 foo_bar(struct foo* foo, const int qux, const float xyzzy)
   1097 {
   1098   ...
   1099 }
   1100 .Ed
   1101 .Pp
   1102 Ordonner les arguments d'une fonction comme suit :
   1103 .Bl -enum -compact
   1104 .It
   1105 pour une fonction d'interface, la variable sur laquelle la fonction
   1106 opère ;
   1107 .It
   1108 les données d'entrées ;
   1109 .It
   1110 les données en sortie.
   1111 .El
   1112 .Pp
   1113 Ajouter l'instruction
   1114 .Ql const
   1115 aux variables qui n'ont pas vocation à être modifiées par la fonction.
   1116 Et ce quand bien même leur modification n'aurait aucune conséquence,
   1117 comme pour les variables de données simples, copiées à l'appel de la
   1118 fonction.
   1119 L'objet étant de souligner qu'elles sont des variables en entrée :
   1120 .Bd -literal -offset Ds
   1121 static void
   1122 foo
   1123   (struct foo* foo,
   1124    constr struct bar* bar,
   1125    const int longueur,
   1126    const int* liste,
   1127    int* resultat);
   1128 
   1129 static INLINE double
   1130 madd(const double a, const double b, const double c)
   1131 {
   1132   return a*b + c;
   1133 }
   1134 .Ed
   1135 .Pp
   1136 Ne passer en copie que les seuls paramètres en entrée de la fonction de
   1137 type primitif
   1138 .Pq Vt char , int , double , No énumération, ... .
   1139 Utiliser un pointeur constant dès lors que le paramètre d'entrée est
   1140 de type structuré, afin d'éviter le surcoût de sa copie à chaque appel de
   1141 fonction ; son occupation mémoire étant a priori plus important
   1142 qu'une donnée simple.
   1143 .Pp
   1144 Les paramètres d'une fonction peuvent ne pas être utilisés à l'intérieur
   1145 de celle-ci.
   1146 C'est notamment le cas si les paramètres ne sont utiles que pour
   1147 répondre à un profil de fonction spécifique ou dans un contexte de
   1148 compilation particulier, par exemple pour le débogage.
   1149 Lister ces paramètres en en-tête de la fonction, après
   1150 la définition des variables locales, en les préfixant d'une conversion
   1151 explicite vers un type vide :
   1152 .Bd -literal -offset Ds
   1153 static void
   1154 foo(int x, int y, int z)
   1155 {
   1156   int i = 0;
   1157   (void)y, (void)z; /* Paramètres inutilisés */
   1158 
   1159   i = bar(x);
   1160   if (i < 42) {
   1161     printf("Foobar\en");
   1162   }
   1163 }
   1164 .Ed
   1165 .Pp
   1166 Cette conversion explicite quels paramètres sont ignorés, en plus de
   1167 désactiver les avertissements de compilation quant à la définition de
   1168 paramètres non utilisés
   1169 .Pq option Fl Wunused-parameter No de Xr gcc 1 .
   1170 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1171 .Sh LES VARIABLES
   1172 Limiter le nombre de variables par bloc entre 5 et 10.
   1173 Un nombre de variables trop important peut être le signe d'un manque de
   1174 structure auquel un découpage en sous-fonction(s) pourrait remédier
   1175 .Pq section Sx LES FONCTIONS .
   1176 .Pp
   1177 Initialiser les variables dès leur définition avec sinon une valeur
   1178 valide, au moins une valeur par défaut.
   1179 L'objet étant d'éviter l'utilisation de variables non initialisées.
   1180 D'apparence peu critique pour les variables de type primitif, cette
   1181 initialisation l'est bien plus pour les variables structurées, dont la
   1182 liste des membres peut changer.
   1183 Si elle existe, utiliser la constante proposée avec la définition du
   1184 type structuré pour initialiser une variable de ses variables
   1185 .Pq voir section Sx LES STRUCTURES .
   1186 En son absence n'initialiser que le premier membre de la variable ; le
   1187 language C assure alors que les autres membres seront initialisés à
   1188 zéro.
   1189 De même pour un tableau alloué sur la pile, initialiser son premier
   1190 élément suffit à garantir que le reste du tableau sera initialisé à
   1191 zero :
   1192 .Bd -literal -offset Ds
   1193 struct foo foo = FOO_DEFAULT;
   1194 struct bar bar = {0};
   1195 int qux[10] = {0};
   1196 int i = 0;
   1197 .Ed
   1198 .Pp
   1199 Au sein d'une même fonction, définir les variables au plus proche de
   1200 leur utilisation de sorte à ce que le contexte dans lequel elles sont
   1201 utilisées participe à les caractériser.
   1202 Par exemple, une variable
   1203 .Va i
   1204 utilisée dans un bloc comme variable temporaire, et comme indice de
   1205 boucle dans un autre, gagnera en expressivité et en robustesse à être
   1206 définie localement à chaque bloc ;
   1207 les deux variables étant alors, par construction, non seulement séparées
   1208 mais aussi sans effet de bord de l'une sur l'autre :
   1209 .Bd -literal -offset Ds
   1210 if(foo) {
   1211   const int i = bar();
   1212   if (i > max_i) max_val = i;
   1213   if (i < min_i) min_val = i;
   1214 } else {
   1215   int i = 0;
   1216   for(i = 0; i < N; ++i) qux(i);
   1217 }
   1218 .Ed
   1219 .Pp
   1220 Regrouper les définitions des variables dès lors qu'elles sont liées
   1221 sémantiquements.
   1222 Les trier ensuite par taille mémoire décroissante, et enfin par ordre
   1223 alphabétique :
   1224 .Bd -literal -offset Ds
   1225 /* Bibliothèque Foo */
   1226 struct foo_args foo_args = FOO_ARGS_DEFAULT;
   1227 struct foo* foo = NULL;
   1228 
   1229 /* Tableau à traiter */
   1230 double* liste = NULL;
   1231 int capacite = 0;
   1232 int longueur = 0;
   1233 .Ed
   1234 .Pp
   1235 Trier la définition des variables par taille mémoire tend à limiter le
   1236 nombre d'octets de remplissage que le compilateur C ajoute pour garantir
   1237 l'alignement mémoire de chaque variable eu égard à leur type.
   1238 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1239 .Sh LES CONSTANTES
   1240 Utiliser une énumération si les constantes à définir sont liées
   1241 sémantiquement, et une macro sinon :
   1242 .Bd -literal -offset Ds
   1243 #define ID_INVALIDE ((unsigned)-1)
   1244 
   1245 enum { X, Y, Z };
   1246 
   1247 enum attribut {
   1248   POSITION,
   1249   NORMALE,
   1250   TEXCOORD
   1251 };
   1252 .Ed
   1253 .Pp
   1254 Pour une énumération qui utilise des valeurs par défaut,
   1255 ajouter si besoin une dernière constante qui définit le nombre de
   1256 constantes valides ;
   1257 sa valeur sera ainsi automatiquement mise à jour à chaque changement de
   1258 l'énumération.
   1259 Une telle constante peut alors servir à définir la cardinalité d'un
   1260 tableau, comme valeur du dernier indice marquant la fin d'une itération,
   1261 ou encore comme valeur vis à vis de laquelle la validité d'une variable
   1262 du type énuméré peut être vérifiée :
   1263 .Bd -literal -offset Ds
   1264 enum molecule {
   1265   CH4,
   1266   CO,
   1267   CO2,
   1268   H2O,
   1269   N2O,
   1270   O3,
   1271 
   1272   NOMBRE_DE_MOLECULES
   1273 };
   1274 
   1275 /* Vérifier qu'une constante définie une molecule valide */
   1276 #define MOLECULE_EST_VALIDE(Mol) \e
   1277   ((unsigned)(Mol) < NOMBRE_DE_MOLECULES)
   1278 
   1279 static const char* NOM_DES_MOLECULES[NOMBRE_DE_MOLECULES] = {
   1280   "CH4", "CO", "CO2", "H2O", "N2O", "O3"
   1281 };
   1282 .Ed
   1283 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1284 .Sh LES STRUCTURES
   1285 Définir les structures en en-tête de fichier
   1286 .Pq section Sx LA STRUCTURE D'UN FICHIER SOURCE ,
   1287 à l'exeption des structures locales à une fonction.
   1288 .Pp
   1289 Lister les variables membres d'une structure suivant la même convention
   1290 que pour la définition des variables d'un bloc
   1291 .Pq section Sx LES VARIABLES Ns
   1292  :
   1293 les regrouper d'abord par sémantique, puis les trier par occupation
   1294 mémoire décroissante, et enfin par ordre alphabétique.
   1295 .Pp
   1296 Ne définir qu'une variable membre par ligne.
   1297 .Pp
   1298 Pour une structure dont aucune fonction ne permet d'en initialiser les
   1299 membres, définir une constante qui fixe leur valeur par défaut.
   1300 Suffixer cette constante par
   1301 .Ql DEFAULT
   1302 ou
   1303 .Ql NULL
   1304 fonction de si une variable structurée ainsi initialisée est une donnée
   1305 valide ou non.
   1306 Déclarer cette constante en tant que variable statique et l'initialiser par
   1307 une macro de même nom, différencié de la variable constante par un
   1308 double tiret bas final
   1309 .Ql __ Ns
   1310  :
   1311 .Bd -literal -offset Ds
   1312 struct arg {
   1313   char* fichier; /* NULL <=> entrée standard */
   1314   int verbosite;
   1315 };
   1316 #define ARG_DEFAULT__ {NULL, 0}
   1317 static const struct arg ARG_DEFAULT = ARG_DEFAULT__;
   1318 
   1319 struct chaine {
   1320   char* mem;
   1321   int longueur;
   1322   int capacite;
   1323 };
   1324 #define CHAINE_NULL__ {NULL,0,0}
   1325 static const struct chaine CHAINE_NULL = CHAINE_NULL__;
   1326 .Ed
   1327 .Pp
   1328 N'utiliser la macro que lorsqu'il est impossible d'utiliser la variable
   1329 constante, en l'occurence pour initialiser, dès sa définition, les
   1330 membres d'une autre variable structurée :
   1331 .Bd -literal -offset Ds
   1332 struct qux {
   1333   struct chaine foo;
   1334   int bar;
   1335 };
   1336 #define QUX_DEFAULT__ {CHAINE_NULL__, 0}
   1337 static const struct qux QUX_DEFAULT = QUX_DEFAULT__;
   1338 .Ed
   1339 .Pp
   1340 Éviter d'utiliser une déclaration typedef des structures afin
   1341 d'autoriser leur déclaration anticipée.
   1342 Et l'utilisation de pointeur vers une donnée structurée sans avoir sa
   1343 définition.
   1344 Si un déclaration typedef est néanmoins souhaitée, nommer le type
   1345 structuré en suivant la convention de nommage des déclarations typedef
   1346 .Pq section Sx Les déclarations de types .
   1347 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1348 .Sh LES MACROS
   1349 Pour définir une séquence d'instructions,
   1350 préférer l'utilisation de fonctions aux macros.
   1351 Déclarer la fonction avec la directive
   1352 .Sy INLINE
   1353 si son coût d'appel est un enjeu
   1354 .Pq section Sx Les symboles internes à une unité de compilation .
   1355 .Pp
   1356 Regrouper la séquence d'instructions d'une macro dans un bloc terminé
   1357 par l'instruction
   1358 .Ql (void)0 .
   1359 Elle peut ainsi être utilisée comme unique expression d'une structure de
   1360 contrôle, et force l'ajout d'un point virgule
   1361 .Ql \&;
   1362 .Pq ou d'une virgule Ql \&,
   1363 après son utilisation, telle n'importe quelle autre instruction C.
   1364 .Pp
   1365 En C, il est plus courant d'encapsuler les instructions d'une macro
   1366 dans une structure de contrôle
   1367 .Ql do { ... } while (0)
   1368 plutôt que dans un bloc terminé par la converstion de l'entier zéro vers
   1369 un type vide
   1370 .Ql (void)0 .
   1371 Si les deux écritures répondent aux mêmes objectifs, cette dernière
   1372 convention évite les avertissements émis par certains compilateur quant
   1373 à l'utilisation d'une expression conditionnelle constante dans
   1374 .Ql while (0) .
   1375 .Pp
   1376 Ouvrir le bloc sur la même ligne que le nom de la macro, en ajoutant un
   1377 espace avant l'acolade
   1378 .Ql { .
   1379 Indenter le contenu du bloc par rapport à la directive de définition de
   1380 la macro.
   1381 Justifer à droite les caractères anti-slash
   1382 .Ql \e
   1383 en fin de chaque ligne de sorte à faciliter la lecture de la séquence
   1384 d'instructions développée par la macro :
   1385 .Bd -literal -offset Ds
   1386 #define FOO(X, Y) {                                        \e
   1387   if ((X) == (Y)) printf("Bar \en");                        \e
   1388   (Y) += 2;                                                \e
   1389 } (void)0
   1390 .Ed
   1391 .Pp
   1392 À noter que dans l'exemple qui précède, les caractères anti-slash
   1393 .Ql \e
   1394 sont alignés en suivant des contraintes d'édition propres à ce manuel.
   1395 Dans un fichier source, positioner l'anti-slash en tant que dernier
   1396 caractère de lignes qui occupent la longueur maximale autorisée
   1397 .Pq section Sx LA LONGUEUR DES LIGNES .
   1398 .Pp
   1399 Pour une macro dont la portée est l'unité de compilation, ne pas changer
   1400 le déroulé des instructions de son contexte d'appel, par exemple en
   1401 intégrant une directive
   1402 .Ql return .
   1403 Son utilisation contredirait l'exécution séquentielle du code et ce
   1404 faisant nuirait à sa lisibilité.
   1405 Il n'est donc
   1406 .Em pas
   1407 recommandé de définir une macro comme suit :
   1408 .Bd -literal -offset Ds
   1409 #define FOO(X) {
   1410   if (bar(X))
   1411     return -1;
   1412 } (void)0
   1413 .Ed
   1414 .Pp
   1415 Ne pas présupposer l'existance de variables externes à la macro,
   1416 exeption faite des variables globales.
   1417 L'objet étant de ne pas lier son bon fonctionnement au contexte local
   1418 dans lequel elle est développée.
   1419 L'écriture qui suit est donc
   1420 .Em découragée Ns
   1421  :
   1422 .Bd -literal -offset Ds
   1423 #define BAR(X,Y) {
   1424   z = (X) + (Y);
   1425   if (xyzzy(z))
   1426     z += 1;
   1427 }
   1428 .Ed
   1429 .Pp
   1430 Contrairement aux macros définies à l'échelle d'une unité de
   1431 compilation, une macro locale peut non seulement changer le fil
   1432 d'exécution du contexte d'appel, mais aussi utiliser des variables
   1433 externes.
   1434 Et ce précisément en raison de son caractère local, qui lie étroitement
   1435 la macro à son seul contexte d'utilisation.
   1436 .Bd -literal -offset Ds
   1437 static int
   1438 foo(const int x)
   1439 {
   1440   char s[10] = {0};
   1441   int line = 0;
   1442   int err = 0;
   1443 
   1444   #define CALL(Func) {                                    \e
   1445     if((err=(Func)) != 0) {                               \e
   1446       line = __LINE__;                                    \e
   1447       goto error;                                         \e
   1448     }                                                     \e
   1449   } (void)0
   1450 
   1451   CALL(bar(x, s));
   1452   CALL(quux(s));
   1453 
   1454   #undef CALL
   1455 
   1456 exit:
   1457   return err;
   1458 error:
   1459   fprinf(stderr, "erreur %d ligne %d\en", err, line);
   1460   goto exit;
   1461 }
   1462 .Ed
   1463 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1464 .Sh LES ALLOCATIONS DYNAMIQUES
   1465 Préférer l'interface d'allocation proposée par la
   1466 bibliothèque
   1467 .Ql RSys
   1468 via son fichier d'en-tête
   1469 .In rsys/mem_allocator.h .
   1470 Elle enrichit la gestion de la mémoire dynamique proposée par la
   1471 bibliothèque C standard, notamment en enregistrant la quantité de
   1472 mémoire allouée.
   1473 .Pp
   1474 Utiliser dès lors les fonctions
   1475 .Fn mem_alloc ,
   1476 .Fn mem_calloc
   1477 et
   1478 .Fn mem_realloc
   1479 pour allouer dynamiquement de la mémoire.
   1480 Leur profil est celui des fonctions équivalentes proposées par la
   1481 bibliothèque C, à savoir ces mêmes fonctions mais sans le prefixe
   1482 .Ql mem_ .
   1483 .Pp
   1484 Privilégier la fonction
   1485 .Fn mem_calloc
   1486 à
   1487 .Fn mem_alloc
   1488 de sorte à initialiser la mémoire allouée à zéro, et d'éviter ainsi
   1489 d'utiliser des données non initialisées.
   1490 .Pp
   1491 Ne pas convertir le pointeur retourné par les fonctions d'allocation.
   1492 La conversion d'un pointeur vide vers n'importe quel autre type de
   1493 pointeur est déjà assuré par le langage C.
   1494 .Pp
   1495 Définir la taille du bloc mémoire à allouer via le type pointé par la
   1496 variable destination :
   1497 .Bd -literal -offset Ds
   1498 p = mem_calloc(42, sizeof(*p));
   1499 .Ed
   1500 .Pp
   1501 L'alternative qui consiste à épeller le type pointé en argument de
   1502 .Ql sizeof
   1503 non seulement nuit à la lisibilité des sources, mais laisse en plus
   1504 l'opportunité d'introduire un bogue dès lors que le type de pointeur
   1505 est mis à jour mais pas le nom du type renseigné à
   1506 .Ql sizeof .
   1507 .Pp
   1508 Utiliser la fonction
   1509 .Fn mem_alloc_aligned
   1510 pour allouer un bloc mémoire dont l'adresse doit être alignée sur un
   1511 nombre d'octets spécifique.
   1512 Utiliser la fonction
   1513 .Xr memset 3 ,
   1514 de la bibliothèque C standard, pour forcer la mise à zéro du bloc ainsi
   1515 alloué sinon rempli d'octets
   1516 aléatoires :
   1517 .Bd -literal -offset Ds
   1518 foo = mem_alloc_aligned(sizeof(*foo), 128/* Alignement */);
   1519 memset(foo, 0, sizeof(*foo));
   1520 .Ed
   1521 .Pp
   1522 Vérifier chaque allocation en testant que l'adresse retournée n'est pas
   1523 .Ql NULL .
   1524 Traiter ce cas comme une erreur et non un bogue
   1525 .Pq section Sx LA GESTION DES ERREURS Ns
   1526  :
   1527 .Bd -literal -offset Ds
   1528   foo = mem_calloc(1, sizeof(*foo);
   1529   if (!foo) {
   1530     res = RES_MEM_ERR;
   1531     goto error;
   1532   }
   1533 .Ed
   1534 .Pp
   1535 Libérer la mémoire allouée via
   1536 .Ql RSys
   1537 avec la fonction
   1538 .Fn  mem_rm
   1539 dont le profil est le même que celui de la fonction
   1540 .Xr free 3 Ns
   1541  :
   1542 .Bd -literal -offset Ds
   1543 mem_rm(foo);
   1544 .Ed
   1545 .Pp
   1546 Détecter la présence de fuites mémoires via la fonction
   1547 .Fn mem_allocated_size
   1548 qui retourne la quantité de mémoire qui reste allouée par la
   1549 bibliothèque :
   1550 .Bd -literal -offset Ds
   1551 int
   1552 main(void)
   1553 {
   1554   size_t sz = 0;
   1555   int err = 0;
   1556 
   1557   ...
   1558 
   1559   if ((sz = mem_alloc_aligned()) != 0) {
   1560     fprintf(stderr, "Fuites mémoires : %lu octets\en", sz);
   1561     if (err == 0) err = 1;
   1562   }
   1563   return err;
   1564 }
   1565 .Ed
   1566 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1567 .Ss Les allocateurs mémoire
   1568 Dans son fichier d'en-tête
   1569 .In rsys/mem_allocator.h ,
   1570 la bibliothèque
   1571 .Ql RSys
   1572 définit en plus une interface d'allocateur mémoire.
   1573 Au contraire de son interface d'allocation qui enregistre la mémoire
   1574 alloué globalement par la bibliothèque,
   1575 chaque allocateur enregistre ses seules allocations.
   1576 .Pp
   1577 Plusieurs types d'allocateurs sont proposés par la bibliothèque
   1578 .Ql RSys ,
   1579 chacun mettant en oeuvre une politique d'allocation qui lui est propre.
   1580 Si bien qu'en fonction du contexte, un type d'allocateur particulier
   1581 peut s'avérer plus approprié, par exemple pour réduire les coûts
   1582 d'allocations/désallocations.
   1583 Décrire les différents types d'allocateurs définis dans la bibliothèque
   1584 .Ql RSys
   1585 sort du cadre de cette documentation.
   1586 Le lecteur est invité à se référer à son fichier d'en-tête
   1587 .In rsys/mem_allocator.h
   1588 pour plus d'informations.
   1589 .Pp
   1590 Les convention listées précédemment quant aux allocation dynamiques
   1591 s'appliquent à l'identique à l'utilisation des allocateurs.
   1592 .Pp
   1593 Utiliser un allocateur consiste à appeler des macros, dont le nom est
   1594 une version en majuscule des fonctions de l'interface d'allocation.
   1595 Avec en plus en premier argument l'addresse de l'allocateur concerné :
   1596 .Bd -literal -offset Ds
   1597 foo = MEM_CALLOC(&mem_default_allocator, 1, sizeof(*foo));
   1598 
   1599 \&...
   1600 
   1601 MEM_RM(&mem_default_allocator, foo);
   1602 
   1603 if (MEM_ALLOCATED_SIZE(&mem_default_allocator)) {
   1604   fprintf(stderr, "Fuites mémoires\en");
   1605 }
   1606 .Ed
   1607 .Pp
   1608 avec
   1609 .Va mem_default_allocator
   1610 l'allocateur par défaut définit par la bibliothèque
   1611 .Ql RSys .
   1612 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1613 .Sh LA GESTION DES ERREURS
   1614 .Sh LES PROGRAMME EN LIGNE DE COMMANDE
   1615 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1616 .Sh FICHIERS
   1617 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1618 .Sh VOIR AUSSI
   1619 .Xr gcc 1 ,
   1620 .Xr feature_test_macros 7
   1621 .Pp
   1622 .Rs
   1623 .%A La Fondation pour le logiciel libre
   1624 .%T Comment utiliser les licences GNU pour vos logiciels
   1625 .%U https://www.gnu.org/licenses/gpl-howto.fr.html
   1626 .Re