star-c.7 (56107B)
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 October 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 421 static int 422 qux(const int xyzzy) 423 { 424 ... 425 } 426 .Ed 427 .Pp 428 À noter que dans l'exemple qui précède, la taille des lignes 429 d'encadrement est limitée par des contraintes d'édition de la présente 430 page de manuel. 431 Dans un fichier source, étendre ces lignes pour qu'elles occupent la 432 longueur maximale recommandée pour une ligne 433 .Pq section Sx LA LONGUEUR DES LIGNES . 434 .Pp 435 Pour expliciter le contexte général d'un fichier, en terme d'utilisation 436 ou d'architecture logicielle, insérer un commentaire en en-tête du 437 fichier en laissant les caractères d'ouverture ou de fermeture de 438 commentaires sur une ligne séparée : 439 .Bd -literal -offset Ds 440 /* 441 * Interface de programmation des tableaux extensibles. 442 * Cette structure de données peut être utilisée avec des 443 * types de données qui ne nécessitent pas de processus 444 * d'initialisation ou de libération et qui peuvent être 445 * copiés bit à bit 446 */ 447 .Ed 448 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 449 .Sh LES FICHIERS D'EN-TÊTE 450 Inclure les fichiers d'en-tête dans l'ordre qui suit : 451 .Bl -enum -compact 452 .It 453 les en-têtes locaux au programme ; 454 .It 455 les en-têtes des dépendances du programme ; 456 .It 457 les en-têtes systèmes et ceux de la bibliothèque C standard. 458 .El 459 .Pp 460 Les fichiers d'en-tête sont ainsi inclus dans l'ordre décroissant de 461 leur niveau d'abstraction. 462 Cet ordre participe à garantir que chaque fichier d'en-tête inclus les 463 en-têtes dont il a lui même besoin, indépendamment des directives 464 d'inclusion qui précèdent sa propre inclusion. 465 Si ce n'est pas le cas, la compilation pourra échouer, symptôme qu'un 466 des fichiers d'en-tête n'est pas auto-consistant. 467 .Pp 468 Dans chaque groupe, trier les directives d'inclusion par ordre 469 alphabétique des fichiers d'en-tête. 470 Si besoin, ajouter un commentaire court, sur la même ligne que la 471 directive d'inclusion, qui explicite la raison pour laquelle la fichier 472 est inclus. 473 .Bd -literal -offset Ds 474 #include "bar.h" 475 #include "foo.h" 476 #include "qux.h" 477 478 #include <baz.h> 479 480 #include <float.h> /* FLT_MAX */ 481 #include <stdio.h> 482 .Ed 483 .Pp 484 S'efforcer de n'inclure que les seuls fichiers d'en-tête 485 réellement nécessaires au fichier ; 486 par exemple par une déclaration anticipée des types structurés à 487 la place d'inclure des en-têtes dans le seul but de déclarer lesdits 488 types. 489 Un enjeu a considérer avec d'autant plus d'attention que le fichier 490 concerné par les inclusions est lui même un fichier d'en-tête, par 491 conséquent amené à être lui même inclus. 492 L'objet étant de limiter autant que possible le nombre de fichiers 493 inclus par unité de compilation, pour limiter les accès disque et ainsi 494 réduire les temps de compilation. 495 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 496 .Sh LA VISIBILITÉ DES SYMBOLES 497 Par défaut, n'exposer aucun symbole 498 .Po 499 option 500 .Fl fvisibility=hidden 501 du compilateur 502 .Xr gcc 1 503 .Pc , 504 à l'exception de ceux de l'interface de programmation d'une 505 bibliothèque. 506 .\"""""""""""""""""""""""""""""""""" 507 .Ss Les symboles d'interface 508 Privilégier l'écriture d'un seul fichier d'en-tête pour exposer 509 l'interface de programmation d'une bibliothèque. 510 Y définir une macro qui exporte les symboles qu'elle déclare dès lors 511 que ce fichier d'en-tête est inclus par une unité de compilation de la 512 bibliothèque. 513 Et qui se contente d'importer ces mêmes symboles si ce même fichier est 514 inclus par un programme tiers : 515 .Bd -literal -offset Ds 516 #include <rsys/rsys.h> 517 518 #if defined(FOO_SHARED_BUILD) 519 #define FOO_API extern EXPORT_SYM 520 else 521 #define FOO_API extern IMPORT_SYM 522 #endif 523 .Ed 524 .Pp 525 Avec : 526 .Bl -dash -compact 527 .It 528 .Sy FOO_SHARED_BUILD 529 une macro définie uniquement à la compilation de la bibliothèque 530 .Po 531 option 532 .Fl DFOO_SHARED_BUILD 533 du compilateur C 534 .Pc Ns 535 ; 536 .It 537 .Sy EXPORT_SYM 538 et 539 .Sy IMPORT_SYM 540 des directives définies dans la bibliothèque 541 .Ql RSys . 542 Elles enrichissent le langage C d'une gestion explicite de la visibilité 543 des symboles. 544 .El 545 .Pp 546 Utiliser cette macro à la déclaration des variables et constantes 547 d'interfaces : 548 .Bd -literal -offset Ds 549 /* Variables globales de l'interface de programmation */ 550 FOO_API const struct foo foo_plugh; 551 FOO_API const struct foo foo_xyzzy; 552 .Ed 553 .Pp 554 Déclarer le prototype des fonctions d'interface entre les directives 555 .Sy BEGIN_DECLS 556 et 557 .Sy END_DECLS , 558 elles aussi définies dans la bibliothèque 559 .Ql RSys 560 .Pq en-tête In rsys/rsys.h . 561 Ainsi, le fichier d'en-tête peut être inclus par un programe C++ : 562 .Bd -literal -offset Ds 563 BEGIN_DECLS 564 565 FOO_API void 566 foo_bar 567 (int i, 568 int* j); 569 570 FOO_API int 571 foo_qux 572 (double d, 573 int i); 574 575 END_DECLS 576 .Ed 577 .\"""""""""""""""""""""""""""""""""" 578 .Ss Les symboles internes partagés 579 Pour les fichiers d'en-tête internes au programme, utiliser la directive 580 .Sy LOCAL_SYM , 581 définie dans le fichier 582 .In rsys/rsys.h 583 de la bibliothèque 584 .Ql RSys , 585 pour déclarer les variables globales et prototypes de fonctions. 586 Ainsi leur symbole n'est pas exposé à l'extérieur du programme. 587 .Bd -literal -offset Ds 588 #include <rsys/rsys.h> 589 590 extern LOCAL_SYM char bar[128]; 591 592 extern LOCAL_SYM void 593 quux 594 (char* tab, 595 size_t length); 596 .Ed 597 .Pp 598 Cette directive est redondante si le compilateur est configuré pour 599 masquer par défaut tous les symboles 600 .Po 601 option 602 .Fl fvisibility=hidden 603 de 604 .Xr gcc 1 605 .Pc . 606 Utiliser 607 .Sy LOCAL_SYM 608 permet néanmoins de s'exonérer de cet a priori, tout en uniformisant 609 les déclarations des fonctions et variables en explicitant pour chaque 610 déclaration la visibilité du symbole associé. 611 .\"""""""""""""""""""""""""""""""""" 612 .Ss Les symboles internes à une unité de compilation 613 Utiliser le mot clé 614 .Ql static 615 pour déclarer des variables, constantes, et fonctions visibles 616 uniquement au sein d'une unité de compilation. 617 .Pp 618 C'est notamment le cas des constantes symboliques structurées : 619 .Bd -literal -offset Ds 620 struct foo { 621 int bar; 622 int qux; 623 }; 624 static const struct foo FOO_DEFAULT = {1, 0}; 625 .Ed 626 .Pp 627 Mais aussi des fonctions utilitaires, qu'elles soient 628 propres à un fichier C, ou définies dans un fichier d'en-tête. 629 .Bd -literal -offset Ds 630 static void 631 hello(void) 632 { 633 printf("Hello, world!\en"); 634 } 635 .Ed 636 .Pp 637 Ces fonctions peuvent en plus être déclarées avec la directive 638 .Sy INLINE , 639 définie dans l'en-tête 640 .In rsys/rsys.h 641 de la bibliothèque 642 .Ql RSys , 643 pour suggérer au compilateur de substituer l'appel de la fonction par le 644 corps de celle-ci, de sorte à éviter le surcoût de l'appel. 645 Cette directive est équivalente au mot clé 646 .Ql inline 647 du C99, indisponible dans le dialecte C retenu 648 .Pq section Sx LE LANGAGE C . 649 .Bd -literal -offset Ds 650 static INLINE void 651 foo(void) 652 { 653 printf("bar\en"); 654 } 655 .Ed 656 .Pp 657 Limiter la directive 658 .Sy INLINE 659 aux fonctions élémentaires, destinées à être appelées fréquemment et 660 dont le coût de l'appel pourrait alors s'avérer significatif. 661 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 662 .Sh LES BLOCS 663 Ouvrir chaque bloc sur la même ligne que la directive qui en est à 664 l'origine 665 .Po 666 .Ql do , 667 .Ql enum 668 .Ql for , 669 .Ql if , 670 .Ql struct , 671 .Ql switch , 672 .Ql union , 673 .Ql while 674 .Pc , 675 en séparant par un espace la fin de la directive et le caractère 676 .Ql { 677 qui marque l'ouverture du bloc : 678 .Bd -literal -offset Ds 679 if (foo) { 680 bar(); 681 qux(); 682 } 683 .Ed 684 .Pp 685 Exception faite des fonctions, ou le bloc associé est ouvert sur la 686 ligne qui suit : 687 .Bd -literal -offset Ds 688 static void 689 foo(void) 690 { 691 printf("bar\en"); 692 } 693 .Ed 694 .Pp 695 Fermer un bloc sur une ligne à part sauf s'il est suivi d'une nouvelle 696 structure de contrôle associée à la précédente 697 .Po 698 .Ql if else , 699 .Ql do while 700 .Pc . 701 Dans ce cas, ajouter la nouvelle instruction sur la même ligne que celle 702 utilisée pour fermer le bloc, en la séparant du caractère 703 .Ql } 704 par un espace. 705 .Pp 706 Aligner la fermeture du bloc à l'indentation de sa directive, ou, dans 707 le cas de directives qui se suivent, à l'indentation de la première 708 directive à l'origine des blocs successifs : 709 .Bd -literal -offset Ds 710 if (foo) { 711 bar(); 712 } else { 713 qux(); 714 } 715 .Ed 716 .Pp 717 Écrire sur une seule ligne une directive et les opérations qu'elle 718 contrôle que si la clarté du code n'en est pas impactée. 719 Dans ce cas, l'ouverture et la fermeture du bloc associé se fait sur une 720 seule et même ligne : 721 .Bd -literal -offset Ds 722 if (foo) { bar(); return 0; } 723 .Ed 724 .Pp 725 Ne pas utiliser d'accolades si la structure de contrôle n'est suivie 726 d'aucune ou d'une seule directive écrite sur la même ligne : 727 .Bd -literal -offset Ds 728 while (foo()); 729 730 if (bar) return 0; 731 .Ed 732 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 733 .Sh LES MOTS CLÉS 734 Ajouter un espace après chaque structure de contrôle 735 .Ql if , 736 .Ql switch , 737 .Ql for 738 et 739 .Ql while 740 pour les différencier des appels de fonctions. 741 Ne pas ajouter d'espace après l'ouverture et avant la fermeture des 742 parenthèses qui détourent leur(s) expression(s) : 743 .Bd -literal -offset Ds 744 if (i < 10) { 745 foo(i); 746 } 747 .Ed 748 .Pp 749 Ajouter un espace après chaque point virgule qui sépare les expressions 750 d'une boucle 751 .Ql for 752 sauf si l'expression qui suit est vide : 753 .Bd -literal -offset Ds 754 for (i=0; i<10; foo(i++)); 755 756 for (;;) { /* Boucle infinie */ 757 poll(); 758 if(bar) break; 759 } 760 .Ed 761 .Pp 762 Assimiler l'instruction 763 .Ql sizeof 764 à une fonction ; ne pas insérer d'espace entre le mot clé et son 765 expression entourée de parenthèses : 766 .Bd -literal -offset Ds 767 sz = sizeof(int); 768 .Ed 769 .\"""""""""""""""""""""""""""""""""" 770 .Ss L'instruction Ql switch 771 Limiter à quelques lignes le contenu de chaque 772 .Ql case 773 d'une instruction 774 .Ql switch , 775 celle-ci devant donner à lire la seule répartition des traitements, 776 fonction de la valeur que peut prendre l'expression du 777 .Ql switch . 778 Et non les traitements eux même, sauf s'ils sont triviaux. 779 Un 780 .Ql case 781 au contenu trop fourni est alors le signe d'un manque de structure dans 782 l'écriture du programme. 783 .Pp 784 Toujours ajouter une instruction 785 .Ql default 786 même si l'ensemble des valeurs que pourraient prendre l'expression du 787 .Ql switch 788 est censé être couvert par les différents 789 .Ql case . 790 C'est notamment le cas quand l'expression est une variable 791 d'énumération. 792 Utiliser alors la directive 793 .Sy FATAL , 794 définie par la bibliothèque 795 .Ql RSys 796 .Pq en-tête In rsys/rsys.h , 797 pour signifier un comportement inattendu. 798 Et ainsi pouvoir diagnostiquer une erreur dans la valeur de l'expression 799 du 800 .Ql switch , 801 ou un 802 .Ql case 803 manquant : 804 .Bd -literal -offset Ds 805 switch (i) { 806 case FOO: foo(); break; 807 case BAR: bar(); break; 808 case QUX: qux = 1; break; 809 default: FATAL("Unreachable code\en"); break; 810 } 811 .Ed 812 .Pp 813 Ajouter la directive 814 .Sy FALLTHROUGH , 815 définie dans le fichier d'en-tête 816 .In rsys/rsys.h 817 de la bibliothèque 818 .Ql RSys , 819 en fin des instructions 820 .Ql case 821 qui s'enchaînent. 822 L'ajout de cette directive permet d'expliciter que c'est bien le 823 comportement attendu et non l'oublie d'une instruction 824 .Ql break , 825 en plus d'éviter un possible message d'avertissement à la compilation 826 .Pq option Fl Wimplicit-fallthrough No de Xr gcc 1 Ns 827 : 828 .Bd -literal -offset Ds 829 switch (c) { 830 case 'a': 831 foo = 1; 832 FALLTHROUGH; 833 case 'b': 834 bar = 1; 835 break; 836 default: 837 usage(); 838 break; 839 } 840 .Ed 841 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 842 .Sh LE NOMMAGE 843 .\"""""""""""""""""""""""""""""""""" 844 .Ss Les variables 845 Nommer les variables en minuscules. 846 Utiliser le tiret bas 847 .Ql _ 848 au titre de séparateur entre les termes utilisés dans le nom des 849 variables : 850 .Bd -literal -offset Ds 851 foo_bar 852 .Ed 853 .Pp 854 Expliciter l'objet d'une variable dans son nom avec d'autant plus de 855 précision que sa portée est grande. 856 Une variable locale à un bloc de quelques lignes pourra se contenter 857 d'un nom abrégé tel que 858 .Va tmp 859 pour un résultat temporaire, voire n'être qu'un seul caractère 860 pour un indice 861 .Va i 862 ou un nombre d'éléments 863 .Va n Ns 864 ; leur contexte d'utilisation venant préciser ce que leur nom résume. 865 Ce nom abrégé vient non seulement alléger l'écriture mais aussi en 866 renforcer l'expressivité. 867 Par exemple 868 .Va tableau Ns Bq Va i 869 reste plus clair que 870 .Va tableau Ns Bq Va indice . 871 .Pp 872 Les variables globales sont au contraire à nommer de sorte à décrire ce 873 qu'elles représentent, indépendamment de tout contexte d'utilisation, 874 par construction distant de leur déclaration. 875 Un compteur d'allocations global à un programme aura donc pour nom 876 .Va compteur_allocations 877 plutôt que 878 .Va cpt_allocs . 879 .Pp 880 Pour une variable globale déclarée au niveau de l'interface d'une 881 bibliothèque, préfixer ladite variable avec l'acronyme de la 882 bibliothèque. 883 Un compteur d'allocation global à la bibliothèque 884 .Ql Foo , 885 et déclaré en tant que variable globale de son interface, sera alors 886 nommé 887 .Va foo_compteur_allocations . 888 .\"""""""""""""""""""""""""""""""""" 889 .Ss Les fonctions 890 Nommer les fonctions avec des caractères alphanumérique en minuscules, 891 et séparer les termes qui composent leur nom par un tiret bas 892 .Pq caractère Ql _ . 893 .Pp 894 Donner à une fonction un nom d'autant plus explicite que sa portée est 895 importante. 896 Une fonction utilitaire pourra se contenter d'un nom abrégé, tel que 897 .Fn cmp 898 pour une fonction de comparaison utilisée comme argument d'un appel à 899 .Xr qsort 3 900 au sein d'un fichier C. 901 Là où une fonction partagée entre plusieurs unités de compilation aura 902 un nom plus expressif, tel que 903 .Fn compare_bar , 904 pour notamment expliciter le type 905 .Vt struct bar 906 des variables comparées. 907 Jusqu'à préfixer le nom de la fonction par l'acronyme de la bibliothèque 908 quand elle est une fonction d'interface de ladite bibliothèque. 909 Pour la bibliothèque 910 .Ql Foo , 911 une fonction d'interface sera alors nommée 912 .Fn foo_compare_bar . 913 .\"""""""""""""""""""""""""""""""""" 914 .Ss Les déclarations de types 915 Utiliser des caractères alphanumériques en minuscules pour nommer les 916 structures, unions et énumérations. 917 Utiliser le tiret bas 918 .Ql _ 919 pour séparer les différents termes qui composent leur nom. 920 .Bd -literal -offset Ds 921 struct foo { 922 int bar; 923 int baz 924 }; 925 926 union foo_bar { 927 double qux; 928 int xyzzy; 929 }; 930 .Ed 931 .Pp 932 Utiliser la même convention pour nommer les déclarations typedef. 933 À l'exception du suffixe 934 .Ql _T 935 ajouté au nom de l'identificateur du type, en écho au suffixe 936 .Ql _t 937 souvent utilisé pour ce type de déclaration, mais réservé par le 938 standard POSIX. 939 .Bd -literal -offset Ds 940 typedef int foo_T; 941 typedef char foo_bar_T[256]; 942 .Ed 943 .Pp 944 Ne pas utiliser de déclaration typedef sur les structures, unions et 945 énumérations de sorte à permettre leur déclaration anticipée. 946 .Pp 947 Préfixer le nom d'un type par l'acronyme de la bibliothèque dès lors 948 qu'il est un type déclaré en tant que type de son interface. 949 Par exemple, un type structuré de l'interface de la bibliothèque 950 .Ql Foo 951 sera nommé 952 .Vt struct foo_mon_type . 953 .\"""""""""""""""""""""""""""""""""" 954 .Ss Constantes et macros 955 Utiliser des majuscules pour nommer les constantes symboliques, qu'elles 956 soient des macros, des constantes énumérées, ou des variables déclarées 957 comme constantes. 958 Séparer par un tiret bas 959 .Ql _ 960 les termes qui composent leur nom : 961 .Bd -literal -offset Ds 962 #define FOO_BAR 42 963 964 enum foo { 965 BAR_BAZ, 966 QUX 967 }; 968 969 static const enum foo FOO_XYZZY = BAR_BAZ; 970 .Ed 971 .Pp 972 Nommer une constante ou une macro de manière d'autant plus explicite 973 que sa portée est importante. 974 Une constante définie localement à une fonction pourra se contenter 975 d'un nom abrégé, jusqu'à n'être qu'un seul caractère, par exemple pour 976 un nombre d'éléments constant 977 .Sy N . 978 Là où le nom d'une macro ou d'une constante définie dans un fichier 979 d'en-tête se devra d'être plus explicite, tel que 980 .Sy NOMBRE_ELEMENTS_MAX . 981 Et être préfixée par l'acronyme de la bibliothèque si elle est déclarée 982 comme macro ou constante de son interface. 983 Par exemple, pour la bibliothèque 984 .Ql Foo , 985 .Sy FOO_NOMBRE_ELEMENTS_MAX . 986 .Pp 987 Utiliser la convention typographique dite 988 .Dq camel case 989 pour nommer les arguments des macros ; 990 les termes qui composent leur nom sont séparés par une variation de la 991 casse typographique. 992 Un terme débute par une majuscule, suivi de caractères 993 alphanumériques en minuscules. 994 .Bd -literal -offset Ds 995 #define FOO_BAR(FooBar, Qux) ((FooBar) + (Qux)) 996 .Ed 997 .Pp 998 Ainsi, les arguments de macros sont différenciés des constantes 999 symboliques et des variables. 1000 .Pp 1001 À noter que la macro elle même est nommée selon la même convention que 1002 celle utilisée pour les constante symboliques 1003 .Pq en majuscule et un tiret bas pour séparer ses différents termes . 1004 La parenthèse ouvrante, collée au nom de la macro, permettant de 1005 différencier les 2 cas. 1006 .\"""""""""""""""""""""""""""""""""" 1007 .Ss Les variables et macros internes 1008 Suffixer par deux tirets bas 1009 .Ql __ 1010 les variables membres d'une structure définie publiquement, qui n'ont 1011 cependant une signification qu'en interne des fonctions d'interface de 1012 la structure. 1013 L'enjeu étant de souligner que ces variables ne sont accessibles que par 1014 effet de bord, et ne s'addressent 1015 .Em pas 1016 aux utilisatrices et utilisateurs, qui ne devraient donc pas y accéder 1017 directement : 1018 .Bd -literal -offset Ds 1019 struct foo { 1020 double bar; 1021 int baz; 1022 int* qux__; /* Variable interne */ 1023 }; 1024 .Ed 1025 .Pp 1026 Utiliser le même suffixe en double tirets bas 1027 .Ql __ 1028 pour nommer les variables internes à une macro, afin d'éviter de masquer 1029 les variables définies dans le contexte où la macro est développée : 1030 .Bd -literal -offset Ds 1031 #define FOO(Bar, N) { \e 1032 int i__; \e 1033 for (i__ = 0; i__ < N; Bar(i__), ++i__); \e 1034 } (void)0 1035 .Ed 1036 .Pp 1037 Suffixer les macros d'un fichier d'en-tête par deux tirets bas 1038 .Ql __ 1039 dès lors qu'elles sont propres au fichier d'en-tête, et donc 1040 vraisemblablement inacessibles au delà : 1041 .Bd -literal -offset Ds 1042 #define FOO__(Type, Dim) \e 1043 struct Type { \e 1044 int i[Dim]; \e 1045 float f[Dim]; \e 1046 } 1047 FOO__(bar, 2); 1048 FOO__(baz, 3); 1049 FOO__(qux, 4); 1050 #undef FOO__ 1051 .Ed 1052 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1053 .Sh LES FONCTIONS 1054 S'attacher à ce que chaque fonction reste simple et concise, en ne 1055 s'appliquant à ne lui faire faire qu'une seule chose. 1056 Ce faisant, le corps d'une fonction devrait être lisible sur un ou deux 1057 écran, avec comme référence la taille des terminaux telle que 1058 démocratisée à la fin des années 1970, à savoir 24 lignes. 1059 .Pp 1060 Un indice quant à la taille qu'une fonction devrait s'efforcer à avoir 1061 est donné par ses niveaux d'indentation. 1062 Plus elle compte de niveaux et plus elle devrait être ramassée. 1063 De même, un nombre de variables locales supérieur à dix peut être le 1064 signe d'une fonction trop dense. 1065 .Pp 1066 Écrire les directives qui contrôlent la portée d'une fonction et son 1067 type de retour sur une ligne séparée de son nom. 1068 L'expression régulière 1069 .Ql ^nom_de_fonction 1070 peut ainsi être utilisée pour la recherche d'une fonction dans les 1071 différents fichiers sources. 1072 .Pp 1073 Pour une déclaration, revenir à la ligne avant d'ouvrir la parenthèse de 1074 la fonction, précédée d'une indentation par rapport au nom de la 1075 fonction sur la ligne qui précède. 1076 Puis, lister les arguments de la fonction, en revenant à la ligne après 1077 chacun d'eux et en les alignant les uns par rapport aux autres. 1078 Ajouter la parenthèse fermante 1079 .Ql \&) 1080 et le point virgule 1081 .Ql \&; 1082 sur la ligne du dernier argument, sans espace supplémentaire : 1083 .Bd -literal -offset Ds 1084 extern LOCAL_SYM void 1085 foo_bar 1086 (struct foo* foo, 1087 const int qux, 1088 const float xyzzy); 1089 .Ed 1090 .Pp 1091 Les différentes parties qui composent le profil de la fonction sont 1092 ainsi identifiables par la seule mise en page de sa déclaration. 1093 .Pp 1094 Lors de sa définition, lister les arguments de la fonction sur la même 1095 ligne que le nom de la fonction, sans ajouter d'espace entre le nom de 1096 la fonction et sa parenthèse ouvrante : 1097 .Bd -literal -offset Ds 1098 void 1099 foo_bar(struct foo* foo, const int qux, const float xyzzy) 1100 { 1101 ... 1102 } 1103 .Ed 1104 .Pp 1105 Si la liste des arguments dépasse la longueur maximale d'une ligne 1106 .Pq section Sx LA LONGUEUR DES LIGNES 1107 les lister comme pour une déclaration. 1108 .Pp 1109 Ordonner les arguments d'une fonction comme suit : 1110 .Bl -enum -compact 1111 .It 1112 pour une fonction d'interface, la variable sur laquelle la fonction 1113 opère ; 1114 .It 1115 les données d'entrées ; 1116 .It 1117 les données en sortie. 1118 .El 1119 .Pp 1120 Ajouter l'instruction 1121 .Ql const 1122 aux variables qui n'ont pas vocation à être modifiées par la fonction. 1123 Et ce quand bien même leur modification n'aurait aucune conséquence, 1124 comme pour les variables de données simples, copiées à l'appel de la 1125 fonction. 1126 L'objet étant de souligner qu'elles sont des variables en entrée : 1127 .Bd -literal -offset Ds 1128 static void 1129 foo 1130 (struct foo* foo, 1131 constr struct bar* bar, 1132 const int longueur, 1133 const int* liste, 1134 int* resultat); 1135 1136 static INLINE double 1137 madd(const double a, const double b, const double c) 1138 { 1139 return a*b + c; 1140 } 1141 .Ed 1142 .Pp 1143 Ne passer en copie que les seuls paramètres en entrée de la fonction de 1144 type primitif 1145 .Pq Vt char , int , double , No énumération, ... . 1146 Utiliser un pointeur constant dès lors que le paramètre d'entrée est 1147 de type structuré, afin d'éviter le surcoût de sa copie à chaque appel de 1148 fonction ; son occupation mémoire étant a priori plus important 1149 qu'une donnée simple. 1150 .Pp 1151 Les paramètres d'une fonction peuvent ne pas être utilisés à l'intérieur 1152 de celle-ci. 1153 C'est notamment le cas si les paramètres ne sont utiles que pour 1154 répondre à un profil de fonction spécifique ou dans un contexte de 1155 compilation particulier, par exemple pour le débogage. 1156 Lister ces paramètres en en-tête de la fonction, après 1157 la définition des variables locales, en les préfixant d'une conversion 1158 explicite vers un type vide : 1159 .Bd -literal -offset Ds 1160 static void 1161 foo(int x, int y, int z) 1162 { 1163 int i = 0; 1164 (void)y, (void)z; /* Paramètres inutilisés */ 1165 1166 i = bar(x); 1167 if (i < 42) { 1168 printf("Foobar\en"); 1169 } 1170 } 1171 .Ed 1172 .Pp 1173 Cette conversion explicite quels paramètres sont ignorés, en plus de 1174 désactiver les avertissements de compilation quant à la définition de 1175 paramètres non utilisés 1176 .Pq option Fl Wunused-parameter No de Xr gcc 1 . 1177 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1178 .Sh LES VARIABLES 1179 Limiter le nombre de variables par bloc entre 5 et 10. 1180 Un nombre de variables trop important peut être le signe d'un manque de 1181 structure auquel un découpage en sous-fonction(s) pourrait remédier 1182 .Pq section Sx LES FONCTIONS . 1183 .Pp 1184 Initialiser les variables dès leur définition avec sinon une valeur 1185 valide, au moins une valeur par défaut. 1186 L'objet étant d'éviter l'utilisation de variables non initialisées. 1187 D'apparence peu critique pour les variables de type primitif, cette 1188 initialisation l'est bien plus pour les variables structurées, dont la 1189 liste des membres peut changer. 1190 Si elle existe, utiliser la constante proposée avec la définition du 1191 type structuré pour initialiser ses membres 1192 .Pq voir section Sx LES STRUCTURES . 1193 En son absence, n'initialiser que le premier membre de la variable ; le 1194 language C assure alors que les autres membres seront initialisés à 1195 zéro. 1196 De même pour un tableau alloué sur la pile, initialiser son premier 1197 élément suffit à garantir que le reste du tableau sera initialisé à 1198 zero : 1199 .Bd -literal -offset Ds 1200 struct foo foo = FOO_DEFAULT; 1201 struct bar bar = {0}; 1202 int qux[10] = {0}; 1203 int i = 0; 1204 .Ed 1205 .Pp 1206 Au sein d'une même fonction, définir les variables au plus proche de 1207 leur utilisation de sorte à ce que le contexte dans lequel elles sont 1208 utilisées participe à les caractériser. 1209 Par exemple, une variable 1210 .Va i 1211 utilisée dans un bloc comme variable temporaire, et comme indice de 1212 boucle dans un autre, gagnera en expressivité et en robustesse à être 1213 définie localement à chaque bloc ; 1214 les deux variables étant alors, par construction, non seulement séparées 1215 mais aussi sans effet de bord de l'une sur l'autre : 1216 .Bd -literal -offset Ds 1217 if(foo) { 1218 const int i = bar(); 1219 if (i > max_i) max_val = i; 1220 if (i < min_i) min_val = i; 1221 } else { 1222 int i = 0; 1223 for(i = 0; i < N; ++i) qux(i); 1224 } 1225 .Ed 1226 .Pp 1227 Regrouper les définitions des variables dès lors qu'elles sont liées 1228 sémantiquements. 1229 Les trier ensuite par taille mémoire décroissante, et enfin par ordre 1230 alphabétique : 1231 .Bd -literal -offset Ds 1232 /* Bibliothèque Foo */ 1233 struct foo_args foo_args = FOO_ARGS_DEFAULT; 1234 struct foo* foo = NULL; 1235 1236 /* Tableau à traiter */ 1237 double* liste = NULL; 1238 int capacite = 0; 1239 int longueur = 0; 1240 .Ed 1241 .Pp 1242 Trier la définition des variables par taille mémoire tend à limiter le 1243 nombre d'octets de remplissage que le compilateur C ajoute pour garantir 1244 l'alignement mémoire de chaque variable eu égard à leur type. 1245 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1246 .Sh LES CONSTANTES 1247 Utiliser une énumération si les constantes à définir sont liées 1248 sémantiquement, et une macro sinon : 1249 .Bd -literal -offset Ds 1250 #define ID_INVALIDE ((unsigned)-1) 1251 1252 enum { X, Y, Z }; 1253 1254 enum attribut { 1255 POSITION, 1256 NORMALE, 1257 TEXCOORD 1258 }; 1259 .Ed 1260 .Pp 1261 Pour une énumération qui utilise des valeurs par défaut, 1262 ajouter si besoin une dernière constante qui définit le nombre de 1263 constantes valides ; 1264 sa valeur sera ainsi automatiquement mise à jour à chaque changement de 1265 l'énumération. 1266 Une telle constante peut alors servir à définir la cardinalité d'un 1267 tableau, comme valeur du dernier indice marquant la fin d'une itération, 1268 ou encore comme valeur vis à vis de laquelle la validité d'une variable 1269 du type énuméré peut être vérifiée : 1270 .Bd -literal -offset Ds 1271 enum molecule { 1272 CH4, 1273 CO, 1274 CO2, 1275 H2O, 1276 N2O, 1277 O3, 1278 1279 NOMBRE_DE_MOLECULES 1280 }; 1281 1282 /* Vérifier qu'une constante définie une molecule valide */ 1283 #define MOLECULE_EST_VALIDE(Mol) \e 1284 ((unsigned)(Mol) < NOMBRE_DE_MOLECULES) 1285 1286 static const char* NOM_DES_MOLECULES[NOMBRE_DE_MOLECULES] = { 1287 "CH4", "CO", "CO2", "H2O", "N2O", "O3" 1288 }; 1289 .Ed 1290 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1291 .Sh LES STRUCTURES 1292 Définir les structures en en-tête de fichier 1293 .Pq section Sx LA STRUCTURE D'UN FICHIER SOURCE , 1294 à l'exeption des structures locales à une fonction. 1295 .Pp 1296 Lister les variables membres d'une structure suivant la même convention 1297 que pour la définition des variables d'un bloc 1298 .Pq section Sx LES VARIABLES Ns 1299 : 1300 les regrouper d'abord par sémantique, puis les trier par occupation 1301 mémoire décroissante, et enfin par ordre alphabétique. 1302 .Pp 1303 Ne définir qu'une variable membre par ligne. 1304 .Pp 1305 Pour une structure dont aucune fonction ne permet d'en initialiser les 1306 membres, définir une constante qui fixe leur valeur par défaut. 1307 Suffixer cette constante par 1308 .Ql DEFAULT 1309 ou 1310 .Ql NULL 1311 fonction de si une variable structurée ainsi initialisée est une donnée 1312 valide ou non. 1313 Déclarer cette constante en tant que variable statique et l'initialiser par 1314 une macro de même nom, différenciée de la variable constante par un 1315 double tiret bas final 1316 .Ql __ Ns 1317 : 1318 .Bd -literal -offset Ds 1319 struct arg { 1320 char* fichier; /* NULL <=> entrée standard */ 1321 int verbosite; 1322 }; 1323 #define ARG_DEFAULT__ {NULL, 0} 1324 static const struct arg ARG_DEFAULT = ARG_DEFAULT__; 1325 1326 struct chaine { 1327 char* mem; 1328 int longueur; 1329 int capacite; 1330 }; 1331 #define CHAINE_NULL__ {NULL,0,0} 1332 static const struct chaine CHAINE_NULL = CHAINE_NULL__; 1333 .Ed 1334 .Pp 1335 N'utiliser la macro que lorsqu'il est impossible d'utiliser la variable 1336 constante, en l'occurence pour initialiser, dès sa définition, les 1337 membres d'une autre variable structurée : 1338 .Bd -literal -offset Ds 1339 struct qux { 1340 struct chaine foo; 1341 int bar; 1342 }; 1343 #define QUX_DEFAULT__ {CHAINE_NULL__, 0} 1344 static const struct qux QUX_DEFAULT = QUX_DEFAULT__; 1345 .Ed 1346 .Pp 1347 Éviter d'utiliser une déclaration typedef des structures afin 1348 d'autoriser leur déclaration anticipée. 1349 Et l'utilisation de pointeur vers une donnée structurée sans avoir sa 1350 définition. 1351 Si un déclaration typedef est néanmoins souhaitée, nommer le type 1352 structuré en suivant la convention de nommage des déclarations typedef 1353 .Pq section Sx Les déclarations de types . 1354 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1355 .Sh LES MACROS 1356 Pour définir une séquence d'instructions, 1357 préférer l'utilisation de fonctions aux macros. 1358 Déclarer la fonction avec la directive 1359 .Sy INLINE 1360 si son coût d'appel est un enjeu 1361 .Pq section Sx Les symboles internes à une unité de compilation . 1362 .Pp 1363 Regrouper la séquence d'instructions d'une macro dans un bloc terminé 1364 par l'instruction 1365 .Ql (void)0 . 1366 Elle peut ainsi être utilisée comme unique expression d'une structure de 1367 contrôle, et force l'ajout d'un point virgule 1368 .Ql \&; 1369 .Pq ou d'une virgule Ql \&, 1370 après son utilisation, telle n'importe quelle autre instruction C. 1371 .Pp 1372 En C, il est plus courant d'encapsuler les instructions d'une macro 1373 dans une structure de contrôle 1374 .Ql do { ... } while (0) 1375 plutôt que dans un bloc terminé par la converstion de l'entier zéro vers 1376 un type vide 1377 .Ql (void)0 . 1378 Si les deux écritures répondent aux mêmes objectifs, cette dernière 1379 convention évite les avertissements émis par certains compilateurs quant 1380 à l'utilisation d'une expression conditionnelle constante dans 1381 .Ql while (0) . 1382 .Pp 1383 Ouvrir le bloc sur la même ligne que le nom de la macro, en ajoutant un 1384 espace avant l'acolade 1385 .Ql { . 1386 Indenter le contenu du bloc par rapport à la directive de définition de 1387 la macro. 1388 Justifer à droite les caractères anti-slash 1389 .Ql \e 1390 en fin de chaque ligne de sorte à faciliter la lecture de la séquence 1391 d'instructions développée par la macro : 1392 .Bd -literal -offset Ds 1393 #define FOO(X, Y) { \e 1394 if ((X) == (Y)) printf("Bar \en"); \e 1395 (Y) += 2; \e 1396 } (void)0 1397 .Ed 1398 .Pp 1399 À noter que dans l'exemple qui précède, les caractères anti-slash 1400 .Ql \e 1401 sont alignés en suivant des contraintes d'édition propres à ce manuel. 1402 Dans un fichier source, positioner l'anti-slash en tant que dernier 1403 caractère de lignes qui occupent la longueur maximale autorisée 1404 .Pq section Sx LA LONGUEUR DES LIGNES . 1405 .Pp 1406 Pour une macro dont la portée est l'unité de compilation, ne pas changer 1407 le déroulé des instructions de son contexte d'appel, par exemple en 1408 intégrant une directive 1409 .Ql return . 1410 Son utilisation contredirait l'exécution séquentielle du code et ce 1411 faisant nuirait à sa lisibilité. 1412 Il n'est donc 1413 .Em pas 1414 recommandé de définir une macro comme suit : 1415 .Bd -literal -offset Ds 1416 #define FOO(X) { 1417 if (bar(X)) 1418 return -1; 1419 } (void)0 1420 .Ed 1421 .Pp 1422 Ne pas présupposer l'existance de variables externes à la macro, 1423 exeption faite des variables globales. 1424 L'objet étant de ne pas lier son bon fonctionnement au contexte local 1425 dans lequel elle est développée. 1426 L'écriture qui suit est donc 1427 .Em découragée Ns 1428 : 1429 .Bd -literal -offset Ds 1430 #define BAR(X,Y) { 1431 z = (X) + (Y); 1432 if (xyzzy(z)) 1433 z += 1; 1434 } 1435 .Ed 1436 .Pp 1437 Contrairement aux macros définies à l'échelle d'une unité de 1438 compilation, une macro locale peut non seulement changer le fil 1439 d'exécution du contexte d'appel, mais aussi utiliser des variables 1440 externes. 1441 Et ce précisément en raison de son caractère local, qui lie étroitement 1442 la macro à son seul contexte d'utilisation. 1443 .Bd -literal -offset Ds 1444 static int 1445 foo(const int x) 1446 { 1447 char s[10] = {0}; 1448 int line = 0; 1449 int err = 0; 1450 1451 #define CALL(Func) { \e 1452 if((err=(Func)) != 0) { \e 1453 line = __LINE__; \e 1454 goto error; \e 1455 } \e 1456 } (void)0 1457 1458 CALL(bar(x, s)); 1459 CALL(quux(s)); 1460 1461 #undef CALL 1462 1463 exit: 1464 return err; 1465 error: 1466 fprinf(stderr, "erreur %d ligne %d\en", err, line); 1467 goto exit; 1468 } 1469 .Ed 1470 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1471 .Sh LES ALLOCATIONS DYNAMIQUES 1472 Préférer l'interface d'allocation proposée par la 1473 bibliothèque 1474 .Ql RSys 1475 via son fichier d'en-tête 1476 .In rsys/mem_allocator.h . 1477 Elle enrichit la gestion de la mémoire dynamique proposée par la 1478 bibliothèque C standard, notamment en enregistrant la quantité de 1479 mémoire allouée. 1480 .Pp 1481 Utiliser dès lors les fonctions 1482 .Fn mem_alloc , 1483 .Fn mem_calloc 1484 et 1485 .Fn mem_realloc 1486 pour allouer dynamiquement de la mémoire. 1487 Leur profil est celui des fonctions équivalentes proposées par la 1488 bibliothèque C, à savoir ces mêmes fonctions mais sans le prefixe 1489 .Ql mem_ 1490 .Po 1491 voir 1492 .Xr alloc 3 , 1493 .Xr calloc 3 , 1494 et 1495 .Xr realloc 3 1496 .Pc . 1497 .Pp 1498 Privilégier la fonction 1499 .Fn mem_calloc 1500 à 1501 .Fn mem_alloc 1502 de sorte à initialiser la mémoire allouée à zéro, et d'éviter ainsi 1503 d'utiliser des données non initialisées. 1504 .Pp 1505 Ne pas convertir le pointeur retourné par les fonctions d'allocation. 1506 La conversion d'un pointeur vide vers n'importe quel autre type de 1507 pointeur est déjà assuré par le langage C. 1508 .Pp 1509 Définir la taille du bloc mémoire à allouer via le type pointé par la 1510 variable destination : 1511 .Bd -literal -offset Ds 1512 p = mem_calloc(42, sizeof(*p)); 1513 .Ed 1514 .Pp 1515 L'alternative qui consiste à épeller le type pointé en argument de 1516 .Ql sizeof 1517 non seulement nuit à la lisibilité des sources, mais laisse en plus 1518 l'opportunité d'introduire un bogue dès lors que le type de pointeur 1519 est mis à jour mais pas le nom du type renseigné à 1520 .Ql sizeof . 1521 .Pp 1522 Utiliser la fonction 1523 .Fn mem_alloc_aligned 1524 pour allouer un bloc mémoire dont l'adresse doit être alignée sur un 1525 nombre d'octets spécifique. 1526 Utiliser la fonction 1527 .Xr memset 3 , 1528 de la bibliothèque C standard, pour forcer la mise à zéro du bloc ainsi 1529 alloué sinon rempli d'octets 1530 aléatoires : 1531 .Bd -literal -offset Ds 1532 foo = mem_alloc_aligned(sizeof(*foo), 128/* Alignement */); 1533 memset(foo, 0, sizeof(*foo)); 1534 .Ed 1535 .Pp 1536 Vérifier chaque allocation en testant que l'adresse retournée n'est pas 1537 .Ql NULL . 1538 Traiter ce cas comme une erreur et non un bogue 1539 .Pq section Sx CENTRALISER LA SORTIE D'UNE FONCTION Ns 1540 : 1541 .Bd -literal -offset Ds 1542 foo = mem_calloc(1, sizeof(*foo); 1543 if (!foo) { 1544 res = RES_MEM_ERR; 1545 goto error; 1546 } 1547 .Ed 1548 .Pp 1549 Libérer la mémoire allouée via 1550 .Ql RSys 1551 avec la fonction 1552 .Fn mem_rm 1553 dont le profil est le même que celui de la fonction 1554 .Xr free 3 Ns 1555 : 1556 .Bd -literal -offset Ds 1557 mem_rm(foo); 1558 .Ed 1559 .Pp 1560 Détecter la présence de fuites mémoires via la fonction 1561 .Fn mem_allocated_size 1562 qui retourne la quantité de mémoire qui reste allouée par la 1563 bibliothèque : 1564 .Bd -literal -offset Ds 1565 int 1566 main(void) 1567 { 1568 size_t sz = 0; 1569 int err = 0; 1570 1571 ... 1572 1573 if ((sz = mem_alloc_aligned()) != 0) { 1574 fprintf(stderr, "Fuites mémoires : %lu octets\en", sz); 1575 if (err == 0) err = 1; 1576 } 1577 return err; 1578 } 1579 .Ed 1580 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1581 .Ss Les allocateurs mémoire 1582 Dans son fichier d'en-tête 1583 .In rsys/mem_allocator.h , 1584 la bibliothèque 1585 .Ql RSys 1586 définit en plus une interface d'allocateur mémoire. 1587 Au contraire de son interface d'allocation qui enregistre la mémoire 1588 alloué globalement par la bibliothèque, 1589 chaque allocateur enregistre ses seules allocations. 1590 .Pp 1591 Plusieurs types d'allocateurs sont proposés par la bibliothèque 1592 .Ql RSys , 1593 chacun mettant en oeuvre une politique d'allocation qui lui est propre. 1594 Si bien qu'en fonction du contexte, un type d'allocateur particulier 1595 peut s'avérer plus approprié, par exemple pour réduire les coûts 1596 d'allocations/désallocations. 1597 Décrire les différents types d'allocateurs définis dans la bibliothèque 1598 .Ql RSys 1599 sort du cadre de cette documentation. 1600 Le lecteur est invité à se référer à son fichier d'en-tête 1601 .In rsys/mem_allocator.h 1602 pour plus d'informations. 1603 .Pp 1604 Les convention listées précédemment quant aux allocation dynamiques 1605 s'appliquent à l'identique à l'utilisation des allocateurs. 1606 .Pp 1607 Utiliser un allocateur consiste à appeler des macros, dont le nom est 1608 une version en majuscule des fonctions de l'interface d'allocation. 1609 Avec en plus en premier argument l'addresse de l'allocateur concerné : 1610 .Bd -literal -offset Ds 1611 foo = MEM_CALLOC(&mem_default_allocator, 1, sizeof(*foo)); 1612 1613 \&... 1614 1615 MEM_RM(&mem_default_allocator, foo); 1616 1617 if (MEM_ALLOCATED_SIZE(&mem_default_allocator)) { 1618 fprintf(stderr, "Fuites mémoires\en"); 1619 } 1620 .Ed 1621 .Pp 1622 avec 1623 .Va mem_default_allocator 1624 l'allocateur par défaut définit par la bibliothèque 1625 .Ql RSys . 1626 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1627 .Sh CENTRALISER LA SORTIE D'UNE FONCTION 1628 Utiliser la directive 1629 .Ql goto 1630 pour centraliser les traitements à effectuer en sortie de fonction, tels 1631 les affectations de variables de sorties, les libérations de variables 1632 locales temporaires, ou le renvoie d'une valeur en retour de la fonction. 1633 Regrouper ces traitements en fin de fonction sous le label 1634 .Ql exit 1635 dont la dernière instruction est la valeur retournée par la fonction. 1636 .Pp 1637 De même, centraliser la gestion des erreurs détectées pendant 1638 l'exécutation de la fonction sous un label 1639 .Ql error , 1640 qui vise à revenir à l'état du programme avant l'appel de la fonction, 1641 et à préparer son retour compte tenu de l'erreur. 1642 Ses traitements recouvrent notamment la libération de 1643 l'espace mémorie alloué à destination de l'appelant, la restauration des 1644 données en mise à jour modifiées par la fonction avant la détection de 1645 l'erreur, ou la définition de valeurs à destination des variables en 1646 sortie en conséquence de l'erreur détectée. 1647 .Pp 1648 Placer le label 1649 .Ql error 1650 après le label 1651 .Ql exit . 1652 Terminer la gestion des erreurs par la directive 1653 .Ql goto exit , 1654 de sorte à effectuer les traitements en sortie, 1655 .Em indépendants 1656 de la présence ou non d'une erreur d'exécution, et donc à appliquer en 1657 toute circonstance. 1658 En structurant les labels de la sorte, les traitements en sortie 1659 .Pq label Ql exit 1660 sont ainsi exécutés soit automatiquement au fil du bon déroulé de la 1661 fonction, sans que l'auteur(e) n'est nécessairement à le préciser. 1662 Soit après la détection d'une erreur dont la gestion explicite via la 1663 directive 1664 .Ql goto error 1665 précède la sortie de la fonction et ses traitements associés ; auxquels 1666 renvoit finalement la gestion des erreurs centralisée sous le label 1667 .Ql error . 1668 .Bd -literal -offset Ds 1669 static res_T 1670 foo(const int bar, int** out_list) 1671 { 1672 int* list = NULL; 1673 res_T res = RES_OK; 1674 1675 if (out == NULL) { 1676 res = RES_BAD_ARG; 1677 goto error; 1678 } 1679 1680 if ((list = mem_calloc(42, sizeof(*list)) == NULL) { 1681 res = RES_MEM_ERR; 1682 goto error; 1683 } 1684 1685 if ((res = quux(bar, list)) != RES_OK) goto error; 1686 1687 exit: 1688 if (out_list != NULL) *out_list = list; 1689 return res; 1690 error: 1691 if (list) { mem_rm(list); list = NULL; } 1692 goto exit; 1693 } 1694 .Ed 1695 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1696 .Sh LES PROGRAMMES EN LIGNE DE COMMANDE 1697 Privilégier une interface en ligne de commande pour les programmes 1698 directement exécutables par l'utilisateur. 1699 À la fois simple et légère, elle s'intègre parfaitement aux shells, que 1700 ce soit en session interactive ou via des scripts. 1701 Plus qu'une interface utilisateur elle est ainsi une interface vers le 1702 système UNIX dont le programme peut alors directement tirer partie, que 1703 ce soit en terme de gestion d'entrées/sorties ou de communication 1704 inter-processus avec d'autres utilitaires, par exemple via des tubes 1705 shell. 1706 .Pp 1707 Analyser les arguments du programme en utilisant la fonction 1708 .Xr getopt 3 1709 définie par le standard POSIX.1-2001 dans l'en-tête 1710 .In unistd.h 1711 de la bibliohtèque C. 1712 Cette fonction assure la consistante de l'analyse des arguments et 1713 participe au respect des conventions énoncées par le standard POSIX pour 1714 les utilitaires en ligne de commandes. 1715 .Pp 1716 Proposer l'option 1717 .Fl h 1718 qui affiche le seul synopsis de la commande en guise de résumé de ses 1719 attendus et options. 1720 Réserver la description du programme et de ses options à sa page de 1721 manuel. 1722 Afficher ce même synopsis en cas d'erreur lors de l'analyse des 1723 arguments de sorte à renvoyer l'utilisateur vers la syntaxe de la 1724 commande. 1725 .Bd -literal -offset Ds 1726 static void 1727 usage(FILE* stream) 1728 { 1729 fprintf(stream, "usage: foo [-hv] [-b bar]\en"); 1730 } 1731 1732 int 1733 main(int argc, char** argv) 1734 { 1735 FILE* bar = NULL; 1736 int err = 0; 1737 int opt = 0; 1738 int verbosity = 0; 1739 1740 while ((opt = getopt(argc, argv, "b:hv")) != -1) { 1741 switch (opt) { 1742 case 'a': 1743 if((bar = fopen(optarg, "r")) == NULL) err = 1; 1744 break; 1745 case 'h': usage(stdout); goto exit; 1746 case 'v': verbosity += (verbosity < 3); break; 1747 default: err = 1; break; 1748 } 1749 if (err) { usage(stderr); goto error; } 1750 } 1751 if (bar == NULL) bar = stdin; 1752 1753 if ((err = foo(bar, verbosity)) != 0) goto error; 1754 1755 exit: 1756 if(bar && bar != stdin) fclose(bar); 1757 return err; 1758 error: 1759 goto exit; 1760 } 1761 .Ed 1762 .Pp 1763 Dès que possible, donner la possibilité de lire les données d'entrée du 1764 programme directement sur l'entrée standard. 1765 Il pourra ainsi être chaîné avec un autre processus en charge, par 1766 exemple, de pré-traiter ses données d'entrée. 1767 De même, écrire les données en sortie du programme sur la sortie 1768 standard pour qu'un autre utilitaire puisse en post-traiter le 1769 résultat. 1770 Si plusieurs fichiers d'entrée/de sortie sont lus/écrits par le 1771 programme, définir les données le plus à même d'être pré/post-traitées 1772 pour choisir lesquelles seront lues/écriture sur l'entrée/la sortie 1773 standard. 1774 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1775 .Sh FICHIERS 1776 .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1777 .Sh VOIR AUSSI 1778 .Xr gcc 1 , 1779 .Xr getopt 3 , 1780 .Xr feature_test_macros 7 1781 .Pp 1782 .Rs 1783 .%A IEEE 1784 .%A The Open Group 1785 .%R Base Definitions, POSIX.1-2001 1786 .%T Section 12, Utility Conventions 1787 .Re 1788 .Pp 1789 .Rs 1790 .%A La Fondation pour le logiciel libre 1791 .%T Comment utiliser les licences GNU pour vos logiciels 1792 .%U https://www.gnu.org/licenses/gpl-howto.fr.html 1793 .Re