star-style

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

star-c.7 (53309B)


      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 Septembre 2, 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 du projet ;
     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 des macros 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 en majuscule, 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 la police de caractères utilisée.
    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 auteures et auteurs sont encouragés à configurer leur éditeur de
    306 texture pour 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 minuscules.
    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 .Bd -literal -offset Ds
   1092 void
   1093 foo_bar(struct foo* foo, const int qux, const float xyzzy)
   1094 {
   1095   ...
   1096 }
   1097 .Ed
   1098 .Pp
   1099 Si la liste des arguments dépasse la longueur maximale d'une ligne
   1100 .Pq section Sx LA LONGUEUR DES LIGNES
   1101 les lister comme pour une déclaration.
   1102 .Pp
   1103 Ordonner les arguments d'une fonction comme suit :
   1104 .Bl -enum -compact
   1105 .It
   1106 pour une fonction d'interface, la variable sur laquelle la fonction
   1107 opère ;
   1108 .It
   1109 les données d'entrées ;
   1110 .It
   1111 les données en sortie.
   1112 .El
   1113 .Pp
   1114 Ajouter l'instruction
   1115 .Ql const
   1116 aux variables qui n'ont pas vocation à être modifiées par la fonction.
   1117 Et ce quand bien même leur modification n'aurait aucune conséquence,
   1118 comme pour les variables de données simples, copiées à l'appel de la
   1119 fonction.
   1120 L'objet étant de souligner qu'elles sont des variables en entrée :
   1121 .Bd -literal -offset Ds
   1122 static void
   1123 foo
   1124   (struct foo* foo,
   1125    constr struct bar* bar,
   1126    const int longueur,
   1127    const int* liste,
   1128    int* resultat);
   1129 
   1130 static INLINE double
   1131 madd(const double a, const double b, const double c)
   1132 {
   1133   return a*b + c;
   1134 }
   1135 .Ed
   1136 .Pp
   1137 Ne passer en copie que les seuls paramètres en entrée de la fonction de
   1138 type primitif
   1139 .Pq Vt char , int , double , No énumération, ... .
   1140 Utiliser un pointeur constant dès lors que le paramètre d'entrée est
   1141 de type structuré, afin d'éviter le surcoût de sa copie à chaque appel de
   1142 fonction ; son occupation mémoire étant a priori plus important
   1143 qu'une donnée simple.
   1144 .Pp
   1145 Les paramètres d'une fonction peuvent ne pas être utilisés à l'intérieur
   1146 de celle-ci.
   1147 C'est notamment le cas si les paramètres ne sont utiles que pour
   1148 répondre à un profil de fonction spécifique ou dans un contexte de
   1149 compilation particulier, par exemple pour le débogage.
   1150 Lister ces paramètres en en-tête de la fonction, après
   1151 la définition des variables locales, en les préfixant d'une conversion
   1152 explicite vers un type vide :
   1153 .Bd -literal -offset Ds
   1154 static void
   1155 foo(int x, int y, int z)
   1156 {
   1157   int i = 0;
   1158   (void)y, (void)z; /* Paramètres inutilisés */
   1159 
   1160   i = bar(x);
   1161   if (i < 42) {
   1162     printf("Foobar\en");
   1163   }
   1164 }
   1165 .Ed
   1166 .Pp
   1167 Cette conversion explicite quels paramètres sont ignorés, en plus de
   1168 désactiver les avertissements de compilation quant à la définition de
   1169 paramètres non utilisés
   1170 .Pq option Fl Wunused-parameter No de Xr gcc 1 .
   1171 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1172 .Sh LES VARIABLES
   1173 Limiter le nombre de variables par bloc entre 5 et 10.
   1174 Un nombre de variables trop important peut être le signe d'un manque de
   1175 structure auquel un découpage en sous-fonction(s) pourrait remédier
   1176 .Pq section Sx LES FONCTIONS .
   1177 .Pp
   1178 Initialiser les variables dès leur définition avec sinon une valeur
   1179 valide, au moins une valeur par défaut.
   1180 L'objet étant d'éviter l'utilisation de variables non initialisées.
   1181 D'apparence peu critique pour les variables de type primitif, cette
   1182 initialisation l'est bien plus pour les variables structurées, dont la
   1183 liste des membres peut changer.
   1184 Si elle existe, utiliser la constante proposée avec la définition du
   1185 type structuré pour initialiser ses membres
   1186 .Pq voir section Sx LES STRUCTURES .
   1187 En son absence, n'initialiser que le premier membre de la variable ; le
   1188 language C assure alors que les autres membres seront initialisés à
   1189 zéro.
   1190 De même pour un tableau alloué sur la pile, initialiser son premier
   1191 élément suffit à garantir que le reste du tableau sera initialisé à
   1192 zero :
   1193 .Bd -literal -offset Ds
   1194 struct foo foo = FOO_DEFAULT;
   1195 struct bar bar = {0};
   1196 int qux[10] = {0};
   1197 int i = 0;
   1198 .Ed
   1199 .Pp
   1200 Au sein d'une même fonction, définir les variables au plus proche de
   1201 leur utilisation de sorte à ce que le contexte dans lequel elles sont
   1202 utilisées participe à les caractériser.
   1203 Par exemple, une variable
   1204 .Va i
   1205 utilisée dans un bloc comme variable temporaire, et comme indice de
   1206 boucle dans un autre, gagnera en expressivité et en robustesse à être
   1207 définie localement à chaque bloc ;
   1208 les deux variables étant alors, par construction, non seulement séparées
   1209 mais aussi sans effet de bord de l'une sur l'autre :
   1210 .Bd -literal -offset Ds
   1211 if(foo) {
   1212   const int i = bar();
   1213   if (i > max_i) max_val = i;
   1214   if (i < min_i) min_val = i;
   1215 } else {
   1216   int i = 0;
   1217   for(i = 0; i < N; ++i) qux(i);
   1218 }
   1219 .Ed
   1220 .Pp
   1221 Regrouper les définitions des variables dès lors qu'elles sont liées
   1222 sémantiquements.
   1223 Les trier ensuite par taille mémoire décroissante, et enfin par ordre
   1224 alphabétique :
   1225 .Bd -literal -offset Ds
   1226 /* Bibliothèque Foo */
   1227 struct foo_args foo_args = FOO_ARGS_DEFAULT;
   1228 struct foo* foo = NULL;
   1229 
   1230 /* Tableau à traiter */
   1231 double* liste = NULL;
   1232 int capacite = 0;
   1233 int longueur = 0;
   1234 .Ed
   1235 .Pp
   1236 Trier la définition des variables par taille mémoire tend à limiter le
   1237 nombre d'octets de remplissage que le compilateur C ajoute pour garantir
   1238 l'alignement mémoire de chaque variable eu égard à leur type.
   1239 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1240 .Sh LES CONSTANTES
   1241 Utiliser une énumération si les constantes à définir sont liées
   1242 sémantiquement, et une macro sinon :
   1243 .Bd -literal -offset Ds
   1244 #define ID_INVALIDE ((unsigned)-1)
   1245 
   1246 enum { X, Y, Z };
   1247 
   1248 enum attribut {
   1249   POSITION,
   1250   NORMALE,
   1251   TEXCOORD
   1252 };
   1253 .Ed
   1254 .Pp
   1255 Pour une énumération qui utilise des valeurs par défaut,
   1256 ajouter si besoin une dernière constante qui définit le nombre de
   1257 constantes valides ;
   1258 sa valeur sera ainsi automatiquement mise à jour à chaque changement de
   1259 l'énumération.
   1260 Une telle constante peut alors servir à définir la cardinalité d'un
   1261 tableau, comme valeur du dernier indice marquant la fin d'une itération,
   1262 ou encore comme valeur vis à vis de laquelle la validité d'une variable
   1263 du type énuméré peut être vérifiée :
   1264 .Bd -literal -offset Ds
   1265 enum molecule {
   1266   CH4,
   1267   CO,
   1268   CO2,
   1269   H2O,
   1270   N2O,
   1271   O3,
   1272 
   1273   NOMBRE_DE_MOLECULES
   1274 };
   1275 
   1276 /* Vérifier qu'une constante définie une molecule valide */
   1277 #define MOLECULE_EST_VALIDE(Mol) \e
   1278   ((unsigned)(Mol) < NOMBRE_DE_MOLECULES)
   1279 
   1280 static const char* NOM_DES_MOLECULES[NOMBRE_DE_MOLECULES] = {
   1281   "CH4", "CO", "CO2", "H2O", "N2O", "O3"
   1282 };
   1283 .Ed
   1284 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1285 .Sh LES STRUCTURES
   1286 Définir les structures en en-tête de fichier
   1287 .Pq section Sx LA STRUCTURE D'UN FICHIER SOURCE ,
   1288 à l'exeption des structures locales à une fonction.
   1289 .Pp
   1290 Lister les variables membres d'une structure suivant la même convention
   1291 que pour la définition des variables d'un bloc
   1292 .Pq section Sx LES VARIABLES Ns
   1293  :
   1294 les regrouper d'abord par sémantique, puis les trier par occupation
   1295 mémoire décroissante, et enfin par ordre alphabétique.
   1296 .Pp
   1297 Ne définir qu'une variable membre par ligne.
   1298 .Pp
   1299 Pour une structure dont aucune fonction ne permet d'en initialiser les
   1300 membres, définir une constante qui fixe leur valeur par défaut.
   1301 Suffixer cette constante par
   1302 .Ql DEFAULT
   1303 ou
   1304 .Ql NULL
   1305 fonction de si une variable structurée ainsi initialisée est une donnée
   1306 valide ou non.
   1307 Déclarer cette constante en tant que variable statique et l'initialiser par
   1308 une macro de même nom, différencié de la variable constante par un
   1309 double tiret bas final
   1310 .Ql __ Ns
   1311  :
   1312 .Bd -literal -offset Ds
   1313 struct arg {
   1314   char* fichier; /* NULL <=> entrée standard */
   1315   int verbosite;
   1316 };
   1317 #define ARG_DEFAULT__ {NULL, 0}
   1318 static const struct arg ARG_DEFAULT = ARG_DEFAULT__;
   1319 
   1320 struct chaine {
   1321   char* mem;
   1322   int longueur;
   1323   int capacite;
   1324 };
   1325 #define CHAINE_NULL__ {NULL,0,0}
   1326 static const struct chaine CHAINE_NULL = CHAINE_NULL__;
   1327 .Ed
   1328 .Pp
   1329 N'utiliser la macro que lorsqu'il est impossible d'utiliser la variable
   1330 constante, en l'occurence pour initialiser, dès sa définition, les
   1331 membres d'une autre variable structurée :
   1332 .Bd -literal -offset Ds
   1333 struct qux {
   1334   struct chaine foo;
   1335   int bar;
   1336 };
   1337 #define QUX_DEFAULT__ {CHAINE_NULL__, 0}
   1338 static const struct qux QUX_DEFAULT = QUX_DEFAULT__;
   1339 .Ed
   1340 .Pp
   1341 Éviter d'utiliser une déclaration typedef des structures afin
   1342 d'autoriser leur déclaration anticipée.
   1343 Et l'utilisation de pointeur vers une donnée structurée sans avoir sa
   1344 définition.
   1345 Si un déclaration typedef est néanmoins souhaitée, nommer le type
   1346 structuré en suivant la convention de nommage des déclarations typedef
   1347 .Pq section Sx Les déclarations de types .
   1348 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1349 .Sh LES MACROS
   1350 Pour définir une séquence d'instructions,
   1351 préférer l'utilisation de fonctions aux macros.
   1352 Déclarer la fonction avec la directive
   1353 .Sy INLINE
   1354 si son coût d'appel est un enjeu
   1355 .Pq section Sx Les symboles internes à une unité de compilation .
   1356 .Pp
   1357 Regrouper la séquence d'instructions d'une macro dans un bloc terminé
   1358 par l'instruction
   1359 .Ql (void)0 .
   1360 Elle peut ainsi être utilisée comme unique expression d'une structure de
   1361 contrôle, et force l'ajout d'un point virgule
   1362 .Ql \&;
   1363 .Pq ou d'une virgule Ql \&,
   1364 après son utilisation, telle n'importe quelle autre instruction C.
   1365 .Pp
   1366 En C, il est plus courant d'encapsuler les instructions d'une macro
   1367 dans une structure de contrôle
   1368 .Ql do { ... } while (0)
   1369 plutôt que dans un bloc terminé par la converstion de l'entier zéro vers
   1370 un type vide
   1371 .Ql (void)0 .
   1372 Si les deux écritures répondent aux mêmes objectifs, cette dernière
   1373 convention évite les avertissements émis par certains compilateur quant
   1374 à l'utilisation d'une expression conditionnelle constante dans
   1375 .Ql while (0) .
   1376 .Pp
   1377 Ouvrir le bloc sur la même ligne que le nom de la macro, en ajoutant un
   1378 espace avant l'acolade
   1379 .Ql { .
   1380 Indenter le contenu du bloc par rapport à la directive de définition de
   1381 la macro.
   1382 Justifer à droite les caractères anti-slash
   1383 .Ql \e
   1384 en fin de chaque ligne de sorte à faciliter la lecture de la séquence
   1385 d'instructions développée par la macro :
   1386 .Bd -literal -offset Ds
   1387 #define FOO(X, Y) {                                        \e
   1388   if ((X) == (Y)) printf("Bar \en");                        \e
   1389   (Y) += 2;                                                \e
   1390 } (void)0
   1391 .Ed
   1392 .Pp
   1393 À noter que dans l'exemple qui précède, les caractères anti-slash
   1394 .Ql \e
   1395 sont alignés en suivant des contraintes d'édition propres à ce manuel.
   1396 Dans un fichier source, positioner l'anti-slash en tant que dernier
   1397 caractère de lignes qui occupent la longueur maximale autorisée
   1398 .Pq section Sx LA LONGUEUR DES LIGNES .
   1399 .Pp
   1400 Pour une macro dont la portée est l'unité de compilation, ne pas changer
   1401 le déroulé des instructions de son contexte d'appel, par exemple en
   1402 intégrant une directive
   1403 .Ql return .
   1404 Son utilisation contredirait l'exécution séquentielle du code et ce
   1405 faisant nuirait à sa lisibilité.
   1406 Il n'est donc
   1407 .Em pas
   1408 recommandé de définir une macro comme suit :
   1409 .Bd -literal -offset Ds
   1410 #define FOO(X) {
   1411   if (bar(X))
   1412     return -1;
   1413 } (void)0
   1414 .Ed
   1415 .Pp
   1416 Ne pas présupposer l'existance de variables externes à la macro,
   1417 exeption faite des variables globales.
   1418 L'objet étant de ne pas lier son bon fonctionnement au contexte local
   1419 dans lequel elle est développée.
   1420 L'écriture qui suit est donc
   1421 .Em découragée Ns
   1422  :
   1423 .Bd -literal -offset Ds
   1424 #define BAR(X,Y) {
   1425   z = (X) + (Y);
   1426   if (xyzzy(z))
   1427     z += 1;
   1428 }
   1429 .Ed
   1430 .Pp
   1431 Contrairement aux macros définies à l'échelle d'une unité de
   1432 compilation, une macro locale peut non seulement changer le fil
   1433 d'exécution du contexte d'appel, mais aussi utiliser des variables
   1434 externes.
   1435 Et ce précisément en raison de son caractère local, qui lie étroitement
   1436 la macro à son seul contexte d'utilisation.
   1437 .Bd -literal -offset Ds
   1438 static int
   1439 foo(const int x)
   1440 {
   1441   char s[10] = {0};
   1442   int line = 0;
   1443   int err = 0;
   1444 
   1445   #define CALL(Func) {                                    \e
   1446     if((err=(Func)) != 0) {                               \e
   1447       line = __LINE__;                                    \e
   1448       goto error;                                         \e
   1449     }                                                     \e
   1450   } (void)0
   1451 
   1452   CALL(bar(x, s));
   1453   CALL(quux(s));
   1454 
   1455   #undef CALL
   1456 
   1457 exit:
   1458   return err;
   1459 error:
   1460   fprinf(stderr, "erreur %d ligne %d\en", err, line);
   1461   goto exit;
   1462 }
   1463 .Ed
   1464 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1465 .Sh LES ALLOCATIONS DYNAMIQUES
   1466 Préférer l'interface d'allocation proposée par la
   1467 bibliothèque
   1468 .Ql RSys
   1469 via son fichier d'en-tête
   1470 .In rsys/mem_allocator.h .
   1471 Elle enrichit la gestion de la mémoire dynamique proposée par la
   1472 bibliothèque C standard, notamment en enregistrant la quantité de
   1473 mémoire allouée.
   1474 .Pp
   1475 Utiliser dès lors les fonctions
   1476 .Fn mem_alloc ,
   1477 .Fn mem_calloc
   1478 et
   1479 .Fn mem_realloc
   1480 pour allouer dynamiquement de la mémoire.
   1481 Leur profil est celui des fonctions équivalentes proposées par la
   1482 bibliothèque C, à savoir ces mêmes fonctions mais sans le prefixe
   1483 .Ql mem_
   1484 .Po
   1485 voir
   1486 .Xr alloc 3 ,
   1487 .Xr calloc 3 ,
   1488 et
   1489 .Xr realloc 3
   1490 .Pc .
   1491 .Pp
   1492 Privilégier la fonction
   1493 .Fn mem_calloc
   1494 à
   1495 .Fn mem_alloc
   1496 de sorte à initialiser la mémoire allouée à zéro, et d'éviter ainsi
   1497 d'utiliser des données non initialisées.
   1498 .Pp
   1499 Ne pas convertir le pointeur retourné par les fonctions d'allocation.
   1500 La conversion d'un pointeur vide vers n'importe quel autre type de
   1501 pointeur est déjà assuré par le langage C.
   1502 .Pp
   1503 Définir la taille du bloc mémoire à allouer via le type pointé par la
   1504 variable destination :
   1505 .Bd -literal -offset Ds
   1506 p = mem_calloc(42, sizeof(*p));
   1507 .Ed
   1508 .Pp
   1509 L'alternative qui consiste à épeller le type pointé en argument de
   1510 .Ql sizeof
   1511 non seulement nuit à la lisibilité des sources, mais laisse en plus
   1512 l'opportunité d'introduire un bogue dès lors que le type de pointeur
   1513 est mis à jour mais pas le nom du type renseigné à
   1514 .Ql sizeof .
   1515 .Pp
   1516 Utiliser la fonction
   1517 .Fn mem_alloc_aligned
   1518 pour allouer un bloc mémoire dont l'adresse doit être alignée sur un
   1519 nombre d'octets spécifique.
   1520 Utiliser la fonction
   1521 .Xr memset 3 ,
   1522 de la bibliothèque C standard, pour forcer la mise à zéro du bloc ainsi
   1523 alloué sinon rempli d'octets
   1524 aléatoires :
   1525 .Bd -literal -offset Ds
   1526 foo = mem_alloc_aligned(sizeof(*foo), 128/* Alignement */);
   1527 memset(foo, 0, sizeof(*foo));
   1528 .Ed
   1529 .Pp
   1530 Vérifier chaque allocation en testant que l'adresse retournée n'est pas
   1531 .Ql NULL .
   1532 Traiter ce cas comme une erreur et non un bogue
   1533 .Pq section Sx CENTRALISER LA SORTIE D'UNE FONCTION Ns
   1534  :
   1535 .Bd -literal -offset Ds
   1536   foo = mem_calloc(1, sizeof(*foo);
   1537   if (!foo) {
   1538     res = RES_MEM_ERR;
   1539     goto error;
   1540   }
   1541 .Ed
   1542 .Pp
   1543 Libérer la mémoire allouée via
   1544 .Ql RSys
   1545 avec la fonction
   1546 .Fn  mem_rm
   1547 dont le profil est le même que celui de la fonction
   1548 .Xr free 3 Ns
   1549  :
   1550 .Bd -literal -offset Ds
   1551 mem_rm(foo);
   1552 .Ed
   1553 .Pp
   1554 Détecter la présence de fuites mémoires via la fonction
   1555 .Fn mem_allocated_size
   1556 qui retourne la quantité de mémoire qui reste allouée par la
   1557 bibliothèque :
   1558 .Bd -literal -offset Ds
   1559 int
   1560 main(void)
   1561 {
   1562   size_t sz = 0;
   1563   int err = 0;
   1564 
   1565   ...
   1566 
   1567   if ((sz = mem_alloc_aligned()) != 0) {
   1568     fprintf(stderr, "Fuites mémoires : %lu octets\en", sz);
   1569     if (err == 0) err = 1;
   1570   }
   1571   return err;
   1572 }
   1573 .Ed
   1574 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1575 .Ss Les allocateurs mémoire
   1576 Dans son fichier d'en-tête
   1577 .In rsys/mem_allocator.h ,
   1578 la bibliothèque
   1579 .Ql RSys
   1580 définit en plus une interface d'allocateur mémoire.
   1581 Au contraire de son interface d'allocation qui enregistre la mémoire
   1582 alloué globalement par la bibliothèque,
   1583 chaque allocateur enregistre ses seules allocations.
   1584 .Pp
   1585 Plusieurs types d'allocateurs sont proposés par la bibliothèque
   1586 .Ql RSys ,
   1587 chacun mettant en oeuvre une politique d'allocation qui lui est propre.
   1588 Si bien qu'en fonction du contexte, un type d'allocateur particulier
   1589 peut s'avérer plus approprié, par exemple pour réduire les coûts
   1590 d'allocations/désallocations.
   1591 Décrire les différents types d'allocateurs définis dans la bibliothèque
   1592 .Ql RSys
   1593 sort du cadre de cette documentation.
   1594 Le lecteur est invité à se référer à son fichier d'en-tête
   1595 .In rsys/mem_allocator.h
   1596 pour plus d'informations.
   1597 .Pp
   1598 Les convention listées précédemment quant aux allocation dynamiques
   1599 s'appliquent à l'identique à l'utilisation des allocateurs.
   1600 .Pp
   1601 Utiliser un allocateur consiste à appeler des macros, dont le nom est
   1602 une version en majuscule des fonctions de l'interface d'allocation.
   1603 Avec en plus en premier argument l'addresse de l'allocateur concerné :
   1604 .Bd -literal -offset Ds
   1605 foo = MEM_CALLOC(&mem_default_allocator, 1, sizeof(*foo));
   1606 
   1607 \&...
   1608 
   1609 MEM_RM(&mem_default_allocator, foo);
   1610 
   1611 if (MEM_ALLOCATED_SIZE(&mem_default_allocator)) {
   1612   fprintf(stderr, "Fuites mémoires\en");
   1613 }
   1614 .Ed
   1615 .Pp
   1616 avec
   1617 .Va mem_default_allocator
   1618 l'allocateur par défaut définit par la bibliothèque
   1619 .Ql RSys .
   1620 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1621 .Sh CENTRALISER LA SORTIE D'UNE FONCTION
   1622 Utiliser la directive
   1623 .Ql goto
   1624 pour centraliser les traitements à effectuer en sortie de fonction, tels
   1625 les affectations de variables de sorties, les libérations de variables
   1626 locales temporaires, ou le renvoie d'une valeur en retour de la fonction.
   1627 Regrouper ces traitements en fin de fonction sous le label
   1628 .Ql exit
   1629 dont la dernière instruction est la valeur retournée par la fonction.
   1630 .Pp
   1631 De même, centraliser la gestion des erreurs détectées pendant
   1632 l'exécutation de la fonction sous un label
   1633 .Ql error ,
   1634 qui vise à revenir à l'état du programme avant l'appel de la fonction,
   1635 et à préparer son retour compte tenu de l'erreur.
   1636 Ses traitements recouvrent notamment la libération de
   1637 l'espace mémorie alloué à destination de l'appelant, la restauration des
   1638 données en mise à jour modifiées par la fonction avant la détection de
   1639 l'erreur, ou la définition de valeurs à destination des variables en
   1640 sortie en conséquence de l'erreur détectée.
   1641 .Pp
   1642 Placer le label
   1643 .Ql error
   1644 après le label
   1645 .Ql exit .
   1646 Terminer la gestion des erreurs par la directive
   1647 .Ql goto exit ,
   1648 de sorte à effectuer les traitements en sortie,
   1649 .Em indépendants
   1650 de la présence ou non d'une erreur d'exécution, et donc à appliquer en
   1651 toute circonstance.
   1652 En structurant les labels de la sorte, les traitements en sortie
   1653 .Pq label Ql exit
   1654 sont ainsi exécutés soit automatiquement au fil du bon déroulé de la
   1655 fonction, sans que l'auteur(e) n'est nécessairement à le préciser.
   1656 Soit après la détection d'une erreur dont la gestion explicite via la
   1657 directive
   1658 .Ql goto error
   1659 précède la sortie de la fonction et ses traitements associés ; auxquels
   1660 renvoit finalement la gestion des erreurs centralisée sous le label
   1661 .Ql error .
   1662 .Bd -literal -offset Ds
   1663 static res_T
   1664 foo(const int bar, int** out_list)
   1665 {
   1666   int* list = NULL;
   1667   res_T res = RES_OK;
   1668 
   1669   if (out == NULL) {
   1670     res = RES_BAD_ARG;
   1671     goto error;
   1672   }
   1673 
   1674   if ((list = mem_calloc(42, sizeof(*list)) == NULL) {
   1675     res = RES_MEM_ERR;
   1676     goto error;
   1677   }
   1678 
   1679   if ((res = quux(bar, list)) != RES_OK) goto error;
   1680 
   1681 exit:
   1682   if (out_list != NULL) *out_list = list;
   1683   return res;
   1684 error:
   1685   if (list) { mem_rm(list); list = NULL; }
   1686   goto exit;
   1687 }
   1688 .Ed
   1689 .Sh LES PROGRAMME EN LIGNE DE COMMANDE
   1690 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1691 .Sh FICHIERS
   1692 .\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   1693 .Sh VOIR AUSSI
   1694 .Xr gcc 1 ,
   1695 .Xr feature_test_macros 7
   1696 .Pp
   1697 .Rs
   1698 .%A La Fondation pour le logiciel libre
   1699 .%T Comment utiliser les licences GNU pour vos logiciels
   1700 .%U https://www.gnu.org/licenses/gpl-howto.fr.html
   1701 .Re