L'OP demande une citation directe de la norme - N1570 §6.10.1p3,4 + note de bas de page 168 :
... l'expression de la constante de contrôle est évaluée selon les règles de 6.6. ... Cela inclut l'interprétation des constantes de caractères, ce qui peut impliquer la conversion de séquences d'échappement en membres du jeu de caractères d'exécution. Le fait que la valeur numérique de ces constantes de caractère corresponde à la valeur obtenue lorsqu'une constante de caractère identique apparaît dans une expression (autrement que dans une directive #if ou #elif) est défini par l'implémentation. 168
[Ainsi, l'expression constante dans la directive #if et l'instruction if suivantes n'est pas garantie d'être évaluée à la même valeur dans ces deux contextes.
#if 'z' - 'a' == 25
if ('z' - 'a' == 25)
Donc, oui, ce n'est vraiment pas garanti.
Pour comprendre pourquoi ce n'est pas garanti, il faut d'abord savoir que la norme C n'exige pas les constantes de caractère 'a'
y 'z'
pour avoir les valeurs numériques attribuées à ces caractères par ASCII. Le plus Les implémentations C utilisent aujourd'hui l'ASCII ou un superset, mais il existe un autre encodage appelé EBCDIC qui est encore largement utilisé (uniquement sur les mainframes IBM, mais il y en a encore beaucoup). En EBCDIC, non seulement 'a'
y 'z'
ont des valeurs différentes de l'ASCII, l'alphabet n'est pas une séquence contiguë ! C'est pourquoi l'expression 'z' - 'a' == 25
pourrait ne pas évaluer la vérité en premier lieu.
Vous devez également savoir que la norme C tente de maintenir une distinction entre le codage de texte utilisé pour le code source (le "jeu de caractères source") et le codage de texte que le programme utilisera lors de l'exécution (le "jeu de caractères d'exécution"). C'est ainsi que vous pouvez, au moins en principe, prendre un programme dont le code source est en ASCII et l'exécuter sans modification sur un ordinateur qui utilise EBCDIC, simplement en effectuant une compilation croisée appropriée ; vous n'avez pas besoin de convertir d'abord le texte source en EBCDIC.
Aujourd'hui, le compilateur doit comprendre les deux jeux de caractères s'ils sont différents, mais historiquement, le préprocesseur C ( phases de traduction 1 à 4) et le "compilateur proprement dit" (phases 5 à 7) étaient deux programmes distincts, et #if
sont le seul endroit où le préprocesseur doit connaître le jeu de caractères d'exécution. Ainsi, en faisant en sorte que l'implémentation définisse si le "jeu de caractères d'exécution" utilisé par le préprocesseur correspond à celui utilisé par le compilateur proprement dit, la norme autorise le préprocesseur à faire tout son travail dans le jeu de caractères d'exécution. source ce qui a rendu la vie un peu plus facile en 1989.
Cela dit, je serais très surpris de trouver un compilateur moderne qui ne fasse pas en sorte que les deux expressions soient évaluées à la même valeur, même lorsque les jeux de caractères d'exécution et de source sont grossièrement incompatibles. Les compilateurs modernes ont tendance à avoir intégré les préprocesseurs -- les phases 1 à 7 sont toutes exécutées par le même programme -- et même si ce n'est pas le cas, la charge d'ingénierie consistant à spécialiser le préprocesseur pour faire correspondre son jeu de caractères d'exécution au compilateur proprement dit est triviale de nos jours.
2 votes
Dans le premier cas, le préprocesseur fait le travail
8 votes
La même chose que quoi ? Est-ce que vous comparez
#if 'z' - 'a' == 25
avecif('z' - 'a' == 25)
ou vous demandez pourquoi'z' - 'a'
n'est pas évalué à la même constante sur différentes implémentations.0 votes
Je demande pourquoi il n'est pas évalué à la même constante sur différentes implémentations. J'ai clairement mentionné dans ma question d'évaluer et non de comparer. La réponse de Klutt est ce que je voulais. Je dois attendre une certaine période de temps pour accepter sa réponse, c'est pourquoi j'attends.
0 votes
@wildpointerxx alors la réponse ci-dessous est correcte.