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