Eviter d'inclure un fichier header plusieurs fois

Lorsque l’on écrit un grand programme en C, il est souhaitable de le découper en plusieurs fichiers .c séparés qui correspondent chacun à un module. On associe également à chaque module un fichier .h contenant les définitions des fonctions déclarées dans la module, mais aussi des structures ou des constantes.

Souvent, un module utilise les fonctions, structures ou constantes définies dans un autre module. Leurs définitions sont alors incluses dans le module via le fichier .h. Certains fichiers ., doivent eux-même inclure d’autres fichiers .h, notamment pour réutiliser certaines structures.

En pratique, ces inclusions multiples peuvent poser des problèmes si la définition d’une même structure ou constante est incluse plusieurs fois dans un fichier. Pour éviter ce problème, la solution standard est d’associer un nom unique (généralement une variante du nom du fichier) à chaque fichier .h et de n’inclure ce fichier que si ce nom n’est pas déjà défini. C’est la solution utilisée notamment par le noyau Linux. Voici le contenu du fichier /usr/include/byteswap.h.

/* Copyright (C) 1997-2018 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#ifndef _BYTESWAP_H
#define _BYTESWAP_H	1

#include <features.h>

/* Get the machine specific, optimized definitions.  */
#include <bits/byteswap.h>


/* The following definitions must all be macros since otherwise some
   of the possible optimizations are not possible.  */

/* Return a value with all bytes in the 16 bit argument swapped.  */
#define bswap_16(x) __bswap_16 (x)

/* Return a value with all bytes in the 32 bit argument swapped.  */
#define bswap_32(x) __bswap_32 (x)

/* Return a value with all bytes in the 64 bit argument swapped.  */
#define bswap_64(x) __bswap_64 (x)

#endif /* byteswap.h */

Celui-ci commence par les lignes

#ifndef _BYTESWAP_H
#define _BYTESWAP_H	1

La première regarde si _BYTESWAP_H n’est pas défini. Si c’est le cas, alors cette constante est définie et prend la valeur 1 et le reste du fichier (jusque #endif /* byteswap.h */) est inclus. Si _BYTESWAP_H était déjà définie, alors le contenu du fichier n’est pas inclus pour éviter les doubles définitions.

Ecrit le April 7, 2020