J'ai essayé d'écrire un programme à l'aide de certaines directives de pré-traitement de la compilation conditionnelle au lieu de "if-else" comme suit.
#include<stdio.h> int main () { int x; scanf ("%d",&x); #if (x==5) printf ("x is 5"); #else printf ("x not 5"); #endif }
4 Réponses :
C'est le "pré-processeur". "PRE" signifie "avant". P>
Vous essayez d'utiliser une valeur runtime em> lors du prétraitement! Le préprocesseur bien sûr n'a pas accès à ces informations lors de la construction. P>
Ce problème ne se limite pas aux valeurs d'exécution, mais est plus fondamentale. Même si vous essayiez d'utiliser une constante de temps de compilation (nommée) telle que consexpr int x = 2 code>, vous ne pouvez pas le faire. Ce sont deux langues entrelacées, comme la génération de HTML avec PHP; Le HTML n'a aucune connaissance des variables PHP et le PHP n'a aucune connaissance de ce que Widgets clique sur la page. Ce sont des contextes d'exécution complètement différents sans interaction intégrée ni compatibilité croisée. P>
Curieux de savoir les bowvotes, personnellement. Je pensais que c'était une analogie décente.
En distinguant le "pré-processeur", cette réponse nous dit qu'il y a une activité de préprocesseur et qu'il existe une activité de processeur et que l'activité de préprocesseur arrive avant l'activité du processeur, mais cela ne nous dit pas ce qui est dans l'activité de préprocesseur et de ce qui est dans l'activité du processeur. Donc, il ne dit pas à l'op que x == 5 code> ne peut être évalué que pendant l'activité du processeur si
x code> n'est pas un identifiant de pré-dépannage. Il ne distingue même pas ce qui est un identifiant de préprocesseur d'autres types d'identifiants.
En outre, il est incorrect que "même si vous essayiez d'utiliser une constante de temps de compilée", cela ne fonctionnerait pas, car 2 + 2 + 1 code> est une constante de compilation mais peut également être utilisée. dans les expressions de préprocesseur.
@ERICPOSTPISCHIL Une constante de temps de compilation telle que consexpr int x = 2 code>, qui ne peut pas avoir de composant d'exécution mais ne peut néanmoins être complètement invisible au préprocesseur. Alors, changons-le à "Nommé Compil-Time Constant".
@Ericpostpischil et je n'ai pas reçu votre premier commentaire, alors peut-être que vous pourriez y réécrire? Non, je ne suis pas allé dans une exploration académique des types d'identificateurs - je ne trouve pas que ce mandat -2 cependant.
C n'a pas consexpr code>. C permet à une expression constante i> dans i> dans
#if code>, sauf que, après l'expansion macro et le traitement de
défini code>, tous les identificateurs restants sont remplacés par 0.
En ce qui concerne mon premier commentaire, vous avez dit à OP que quelque chose se passe avant autre chose, mais vous n'avez pas dit ce que chaque quelque chose est. Étant donné que la sémantique était inconnue de OP, utilisons des termes que vous ne connaissez pas la signification de l'illustration, disons "Glurmf" et "Zugmar". OP n'était pas au courant que int x code> définit un
x code> connu uniquement à la ZUGMAR, mais que
#if code> est traité par le glurmf. Votre réponse ne dit simplement pas qu'un identifiant
x code> déclaré avec
int x code> sera traité comme zéro pendant le glurmf. Dire à l'OP que Glurmf est avant que Zugmar ne les informent pas de cela.
@ERICPOSTPISCHIL Il ne dit pas cela parce que cela déforme la situation. L'identifiant x code> déclaré avec
int x code> n'a rien à voir avec le
x code> trouvé dans le glumf, car il est évalué dans un contexte totalement différent. C'est le point du problème, et c'est ce que je [essayé de] expliquer. :) Quoi qu'il en soit, nous pouvons accepter de ne pas être d'accord. Merci pour votre contribution.
Re "L'identifiant X déclaré avec int x code> n'a rien à voir avec le X trouvé dans le glumf, car il est évalué dans un contexte totalement différent.": La réponse ne dit pas cela. Les informations sont simplement manquantes de la réponse.
@Ericpostpischil Oui, il fait - par analogie avec PHP et HTML qui existent dans exactement la même circonstance. Comme je l'ai dit, nous pouvons simplement accepter de ne pas être d'accord maintenant. Passe une bonne soirée.
Supposons que je n'avais jamais vu c avant mais je connaissais php et html. Quel texte dans votre réponse me dit si int x code> est dans l'analogique PHP ou dans l'analogique HTML?
Le prétraitement a lieu La compilation conditionnelle est à des fins différentes. P>
Si le prétraitement a lieu avant la compilation, pourquoi compiler les deux lignes void A [3]; code> et
#Error code> avec clang produisent un message d'erreur pour la première ligne (tableau a Type d'élément incomplet) Avant un message d'erreur pour la deuxième ligne?
@ERICPOSTPISCHIL: Il y a la comme si i> règle. Le compilateur est autorisé à faire les choses différemment et n'a pas besoin de gérer toute la phase de préprocesseur avant de faire une analyse sémantique. La norme n'interdit pas ce que vous dites que vous attendez; Cela n'interdit pas non plus ce que vous signalez.
@Jonathanleffler: Je n'ai pas demandé pourquoi la standard C permet de cela. J'ai demandé comment la déclaration de P__j __ est cohérente avec le comportement de Clang. La spécification de la norme C est compatible avec le comportement de Clang à cet égard. Affirmer que le prétraitement a lieu avant que la compilation ne soit pas compatible avec le comportement de Clang.
@ERICPOSTPISCHIL CLANG n'est pas conforme dans ce cas: La mise en œuvre ne doit pas traduire avec succès une unité de traduction de prétraitement contenant une directive de prétraitement #Error, à moins que cela ne fait partie d'un groupe ignoré par inclusion conditionnelle. I>
@ EricpostPischil standard dans 5.1.1.2 b> phases de traduction i> montre que le prétraitement a lieu avant b> la compilation. Étape 7: Les jetons résultants sont analysées syntaxiquement et sémantiquement et traduites comme une unité de traduction. I>
@P__J____: 5.1.1.2 Spécifie la PRECÉDENCE B> des phases de traduction, pas l'ordre chronologique: "La priorité entre les règles de la syntaxe de traduction est spécifiée par les phases suivantes". Il est incorrect et trompeur d'indiquer que le prétraitement a lieu avant la compilation. Cette fausse déclaration pourrait induire en erreur une personne qui voit un message sur une erreur de phase 7 pour conclure que le prétraitement a terminé avec succès, et donc il n'y a donc pas d'erreurs de phase 1 à 6.
@EricpostPischil Clang n'est pas conforme dans ce cas La mise en œuvre ne doit pas traduire avec succès une unité de traduction de prétraitement contenant une directive de prétraitement #Error, à moins que cela ne fait partie d'un groupe ignoré par inclusion conditionnelle. I>
@P__J__: il se conformait car l'unité de traduction n'est pas traduite avec succès.
Le préprocesseur ne connaît pas les déclarations, les types et tels. Cela ne fonctionne que avec des jetons (et des macros qui se développent finalement à ceux). P>
6.10.1P4 P>
Après tous les remplaçants dues à la macro expansion et à la définie unaire
opérateur ont été effectués, tous les identificateurs restants (y compris
Les personnes lexiquement identiques aux mots-clés) sont remplacées par le numéro PP
0, puis chaque jeton de prétraitement est converti en jeton. P>
blockQuote> x code> n'est pas une expression littérale entière ou une expression littérale entière (littéraux entier + opérateurs) ou une macro expansion à ceux-ci, donc dans un préprocesseur qui le remplace avec
0 Code> ( 6.10.1P4 ).
0 == 5 code> est faux, donc la branche
#else code> est prise. p>
@LightnessRacsinorbit J'ai ajouté une citation de la norme pour supporter cette réclamation. ;-) (Vous me devez maintenant un uppote: p).
Til! Je me suis dirigé vers Coliru pour rassembler des preuves incriminantes contre vous et laissé sous le choc: p merci pour la réf.
opérandes dans Dans la norme C 2018, la clause 6.10.1 nous indique que l'évaluation de l'expression dans un relevé Parce que le Dans une instruction PreProcesseur, vous ne pouvez pas évaluer les variables en fonction des valeurs qui seront définies lors de l'exécution du programme. P> #if code> Les instructions peuvent être uniquement des constantes, les choses définies avec
#define code> et un opérateur code> spécial code>. Tous les autres identifiants de l'expression sont remplacés par 0. Le
x code> dans votre code exemple n'est pas défini avec
#define code>, donc
(x == 5) Code> devient
(0 == 0) code>. p>
#if code> comprend: p>
#define code>) sont remplacées en fonction de leurs définitions. LI>
x code> dans votre code exemple n'est pas défini avec
#define code>, il est remplacé par 0 dans le
#if code>. Cela se traduit en
(0 == 5) code>, qui est faux, ce code entre le code entre
#if code> et le
#else code> est ignoré. p>
Le préprocesseur ne peut pas utiliser de variables du programme C.
Le préprocesseur fonctionne pendant la compilation. Pour vérifier les valeurs d'exécution, utilisez normalement
si code>.