Pourquoi le préprocesseur C interprète-t-il le mot "linux" comme la constante "1"?



Answers

Cela semble être une "extension GNU" (non documentée): [ correction : j'ai finalement trouvé une mention dans les docs. Voir ci-dessous.]

La commande suivante utilise l'option -dM pour imprimer toutes les définitions de préprocesseur; puisque l'entrée "fichier" est vide, elle montre exactement les macros prédéfinies. Il a été exécuté avec gcc-4.7.3 sur une installation standard d'ubuntu. Vous pouvez voir que le préprocesseur est standard. Au total, il y a 243 macros avec -std=gnu99 et 240 avec -std=c99 ; J'ai filtré la sortie pour la pertinence.

$ cpp --std=c89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

$ cpp --std=gnu89 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

$ cpp --std=c99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1

$ cpp --std=gnu99 -dM < /dev/null | grep linux
#define __linux 1
#define __linux__ 1
#define __gnu_linux__ 1
#define linux 1

Les versions "gnu standard" aussi #define unix . (Utiliser c11 et gnu11 produit les mêmes résultats.)

Je suppose qu'ils avaient leurs raisons, mais il me semble que l'installation par défaut de gcc (qui compile le code C avec -std=gnu89 sauf indication contraire) est non-conforme, et - comme dans cette question - surprenante. Polluer l'espace de noms global avec des macros dont les noms ne commencent pas par un trait de soulignement n'est pas autorisé dans une implémentation conforme. (6.8.10p2: "Tout autre nom de macro prédéfini doit commencer par un trait de soulignement suivi d'une lettre majuscule ou d'un second caractère de soulignement", mais comme mentionné dans l'Appendice J.5 (problèmes de portabilité), ces noms sont souvent prédéfinis.)

Quand j'ai écrit cette réponse à l'origine, je n'ai pas pu trouver de documentation sur gcc à propos de ce problème, mais je l'ai finalement découvert, pas dans le comportement défini par l'implémentation C ni dans les extensions C mais dans la section 3.7.3 , où il note que:

Nous supprimons progressivement toutes les macros prédéfinies qui sont en dehors de l'espace de noms réservé. Vous ne devriez jamais les utiliser dans de nouveaux programmes ...

Question

Pourquoi le préprocesseur C dans GCC interprète-t-il le mot linux (petites lettres) comme la constante 1 ?

test.c:

#include <stdio.h>
int main(void)
{       
    int linux = 5;
    return 0;
}

Résultat de $ gcc -E test.c (arrêt après l'étape de prétraitement):

....
int main(void)
{
    int 1 = 5;
    return 0;
}

Ce qui, bien sûr, donne une erreur.

(BTW: Il n'y a pas #define linux dans le fichier stdio.h.)




D' info gcc (emphase mienne):

-ansi

En mode C, ceci est équivalent à -std=c90 . En mode C ++, il est équivalent à -std=c++98 . Cela désactive certaines fonctionnalités de GCC incompatibles avec ISO C90 (lors de la compilation du code C) ou C ++ standard (lors de la compilation du code C ++), tels que les mots-clés asm et typeof et les macros prédéfinies telles que 'unix' et 'vax ' qui identifient le type de système que vous utilisez. Il permet également la fonction trigraphique ISO indésirable et rarement utilisée. Pour le compilateur C, il désactive la reconnaissance des // commentaires de style C ++ ainsi que du mot-clé inline .

(Il utilise vax dans l'exemple au lieu de linux parce que quand il a été écrit peut-être c'était plus populaire ;-).

L'idée de base est que GCC essaie uniquement de se conformer entièrement aux normes ISO lorsqu'il est -ansi avec l'option -ansi .




Links