web-dev-qa-db-fra.com

Pourquoi <signal.h> empêche-t-il l'utilisation de "si_" comme préfixe pour le nom de certaines variables?

J'ai débogué une étrange erreur de compilation que j'obtenais dans mon code, et j'ai fini par découvrir que je ne pouvais pas utiliser le préfixe si_ pour certains noms de variables (de tout type) si <signal.h> est inclus.

Voici un exemple de code source très simple qui reproduit le problème:

#include <signal.h>

int main(void)
{
    int si_value = 0;

    return 0;
}

Si j'essaye de compiler ceci avec le compilateur GNU C gcc, j'obtiens l'erreur suivante:

> gcc example.c
In file included from /usr/include/signal.h:57:0,
                 from example.c:2:
example.c: In function ‘main’:
example.c:6:9: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
     int si_value = 0;
         ^
example.c:6:9: error: expected expression before ‘.’ token

Néanmoins, si j'utilise un autre nom tel que si_value2, l'erreur n'apparaît pas. Comme référence, j'utilise GCC v7.3.0 sur Ubuntu Mate 18.04.1 LTS. Le même problème est observé avec g++.

Je suppose que ce comportement est dû à une définition de macro à l'intérieur du <signal.h> en-tête, mais après l'avoir parcouru brièvement, je n'arrivais pas à trouver quoi que ce soit de vraiment lié.

Honnêtement, je peux le réparer en utilisant simplement un autre nom. Cependant, ma préoccupation est: comment pourrais-je éviter avec élégance ce type de problème à l'avenir?


Mise à jour: Comme @ F.X. a suggéré, en utilisant gcc -E example.c montre que le nom de la variable est développé (d'où l'erreur):

...
    int 
# 6 "example.c" 3 4
       _sifields._rt.si_sigval 
# 6 "example.c"
                = 0;
...
24
SRG

<signal.h> n'empêche pas réellement d'utiliser si_ comme préfixe sur vos variables. Cependant, la spécification POSIX indique que ce préfixe est réservé, afin de permettre à l'en-tête et aux fonctions de bibliothèque qu'il déclare d'utiliser ces noms, sans avoir à craindre qu'ils n'entrent en conflit avec vos propres variables.

Donc, ce qui se passe ici, c'est que si_value est défini d'une manière ou d'une autre dans le fichier d'en-tête, peut-être en tant que macro ou typedef, et votre tentative d'utiliser le même nom est en conflit avec cela. Si vous avez utilisé si_vy1ghad563nvy43wd cela fonctionnerait probablement, mais théoriquement l'en-tête pourrait utiliser ce nom (pensant qu'il serait peu probable qu'il entre en conflit avec tout ce qu'un programmeur d'applications utiliserait).

C n'a pas de vrais espaces de noms, donc les conventions de dénomination comme celle-ci sont utilisées comme un simple substitut.

23
Barmar

comment pourrais-je éviter avec élégance ce type de problèmes à l'avenir?

Vous vérifiez certains documentation pour les en-têtes que vous utilisez et évitez les noms qui sont documentés comme réservés.

12
Baum mit Augen