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