11
votes

Tout compilateur C où "==" évalue à plus grand qu'un?

Comme quelque chose de non-zéro signifie vrai, mais le > , << / code>, == etc. opérateurs retourner 1 Pour TRUE, je suis curieux s'il y a des compilateurs C notable C où ces opérateurs peuvent entraîner une valeur supérieure à 1 .

En d'autres termes, existe-t-il un compilateur où int i = (a == b) ; entraînerait un comportement non défini si j'avais l'intention d'utiliser i pas comme une valeur booléenne, mais comme entier, et supposait que ce serait soit 0 ou 1 < / code>?


4 commentaires

Ce serait un compilateur notable.


s / notable / / g :-)


Est-ce juste une question «expérimentation de pensée», ou essayez-vous d'écrire du code qui compilera sur tout compilateur C déjà écrit. Si vous êtes dérangé que cela ne fonctionne pas, il suffit d'inverser vos comparaisons. FAUX est toujours 0.


@Neil: J'écris un code qui devrait compiler avec des compilateurs d'environ 1997, et juste pour m'assurer que je me suis "boolerize" avec ? 1: 0 , mais je me demandais si je dois vraiment être ce paranoïaque.


7 Réponses :


19
votes

Non, s'il y a, ils ne sont pas compilateurs C :-) Les mandats standards que les opérateurs relationnels et d'égalité retour 1 pour vrai et 0 pour faux.


La règle pour interprétation des valeurs entières en tant que valeurs booléennes par C indique que 0 est faux et toute autre valeur est vraie. Voir les sections traitant de C11 si / alors / faire / pour , qui contiennent tous la langue comme "tandis que l'expression compare égale à zéro" . Plus précisément:

6.8.4.1/2: Dans les deux formes [de l'instruction if, une avec et l'autre sans une clause d'autre], la première est exécutée si sous-structure l'expression compare inégale à 0. Dans la forme, d'autre la deuxième sous-structure est exécutée si l'expression compare égal à 0.

6.8.5 / 4. Une instruction d'itération [alors, faire et pour] provoque un état appelé le corps de la boucle à exécuter de façon répétée jusqu'à ce que l'expression de contrôle compare égal à 0


Cependant, il est tout à fait explicite ce résultat que vous obtiendrez pour les expressions de type de comparaison, vous obtenez soit 0 ou 1 . Les bits correspondants de la norme C11 pour ceux-ci sont tous sous 6.5 Expressions :

6.5.8 / 6: Chacun des opérateurs <(inférieur à)> (supérieur à), <= (inférieur ou égal à), et> = (supérieur ou égal à) doit céder 1 si la relation est vraie et 0 si elle est fausse.

6.5.9 / 3: Le == (égal) et = (pas égal à) les opérateurs sont analogues aux opérateurs relationnels à l'exception de leur priorité inférieure!. Chacun des rendements des opérateurs 1 si la relation est vraie et 0 si elle est fausse.

05.06.13 / 3: L'opérateur doit céder && 1 si les deux opérandes comparer différent de 0; sinon, il donne 0.

05.06.14 / 3: || l'opérateur doit céder 1 si l'une de ses opérandes comparer l'inégalité à 0; sinon, il donne 0.

6.5.3.3/5: Le résultat de l'opérateur de négation logique! est égal à 0 si la valeur de son opérande compare pas égal à 0, 1 si la valeur de son opérande compare égal à 0.


Et ce comportement va chemin retour à la C99 et C89 (jours ANSI). Les sections C99 traitant des opérateurs relationnels et d'égalité indique également que les valeurs de retour est 0 ou 1.

Et, alors que le projet de C89 ne explicitement dictent les valeurs de retour pour les opérateurs d'égalité, il ne dit:

Le == (égal) et! = (Pas égal à) les opérateurs sont analogues aux opérateurs relationnels à l'exception de leur priorité inférieure.

Et la section Opérateurs relationnels ne État:

Chacun des opérateurs <(inférieur à)> (supérieur à), <= (inférieur ou égal à), et> = (supérieur ou égal à) doit céder 1 si la relation est vraie et 0 si elle est fausse.

Référence: http://flash-gordon.me.uk/ansi.c. txt depuis que je n'ai pas de copies des normes C89 flottant autour. I faire ont la deuxième édition de K & R (ANSI un de 1988) qui dit essentiellement la même chose, dans les sections A7.9 et A7.10 de l'annexe A, le Manuel de référence. Si vous voulez une réponse définitive de la première édition, qui va falloir venir de quelqu'un avec une femme moins enclin à jeter vieilleries.


Addendum:

Selon Michael Burr, qui est soit pas marié ou a une femme plus accommodante que moi en termes de maintien livres anciens: -)

K & R 1ère édition (1978) indique également le même dans 7.6 et 7.7: « Les [tous les opérateurs relationnels] rendement 0 si la relation spécifiée est faux et 1 s'il est vrai. » ... « Les [opérateurs d'égalité] sont exactement analogues aux opérateurs relationnels, à l'exception de leur priorité inférieure. »


12 commentaires

Quand était-ce fixé? Je n'ai pas accès aux normes, en particulier les plus âgées. Je sais que c'est la règle, mais cela est-il également censé être vrai pour les compilateurs pré-C11 (correctement fonctionnels)?


C'était la même chose en C99. Je vais devoir enquêter sur C90 mais je crois que c'était le cas là aussi.


@vsz: Presque tous les compilateurs existants désormais sont pré-C11, vous avez déjà vu des réponses ici citant la norme C99 qui le mandat.Je ne vois pas quelle est la confusion, utilisez-vous un compilateur pré-C99?


@Als: Presque tous les compilateurs existants sont maintenant C99, à l'exception de certains compilateurs fabriqués en 1997 qui sont toujours utilisés pour des processeurs incorporés spécifiques (oui, même de nouveaux), sans spécifier nulle part dans le manuel dont ils sont basés sur (je suppose que non plus âgé que c89).


@vsz, en fait, l'obligation de retourner 1 ou 0 est également vraie pour les compilateurs conformes à l'ANSI, selon les brouillons de la norme ANSI C89 que j'ai vu ( flash-gordon.me.uk/ansi.c.txt ). Donc, à moins que votre compilateur ande que, vous pouvez supposer en toute sécurité 1/0. Et, si cela prédire cela, vous voudrez peut-être envisager de vous joindre au 21ème siècle :-)


@paxdiablo: Pouvez-vous inclure ce commentaire sur l'ANSI C89 dans la réponse afin que je puisse le marquer comme accepté?


Fait pendant que vous tapez ce commentaire, @vsz :-)


Le compilateur doit donner 1 pour vrai, cependant, le compilateur / optimiseur est également libre de substituer toute valeur à condition que le comportement du programme soit inchangé (à moins que votre code essaie de le comparer avec 1, l'optimiseur ne doit pas modifier la valeur pour maintenir la valeur de la valeur. le même résultat final).


Calvin, qui pourrait réellement être dit de tout comportement puisqu'un optimiseur est autorisé à modifier tout ce qui n'a aucun effet de la "machine abstraite" C "comme décrit dans la norme. Cependant, un seul Nitpick: tout l'utilisation du résultat nécessitera qu'il soit 1 ou 0, non seulement le comparer à 1.


(J'avais l'habitude d'avoir une copie de 1ère édition de K & R, mais je l'ai jeté ... soupir)


K & R 1ST Edition (1978) indique également la même chose en 7.6 et 7,7: "Les [opérateurs relationnels] tous donnent 0 si la relation spécifiée est fausse et 1 si elle est vraie." ... "Les [opérateurs d'égalité] sont exactement analogues aux opérateurs relationnels, à l'exception de leur priorité inférieure." Je pense donc que ce comportement a été vrai depuis longtemps pour tous, à l'exception du compilateur de ballon étrange. N'oubliez pas que l'utilisation des résultats d'opérateurs relationnels ou d'égalité dans des expressions arithmétiques telles que a + = = (b == c) peut ne pas être vu tous les jours, mais ils sont assez courants. Ils auraient pu être encore plus communs au cours de leur journée.


Merci, @Michael, je vais ajouter cela à la réponse.



3
votes

Je n'ai pas accès à la norme C, mais selon Wikipedia :

C utilise un type d'entier, où des expressions relationnelles telles que I> J et des expressions logiques connectées par && et || sont définis pour avoir la valeur 1 si true et 0 si faux, alors que les parties de test de si, pendant, pour, etc., traitent toute valeur non nulle comme vraie.

Wikipedia a heureusement les citations correctes, mais comme elles sont références aux livres, je ne sais pas combien d'aide :).


2 commentaires

Je sais cela, je voulais juste être sûr qu'il n'y a aucune exception.


Si la norme le dicte, il n'ya pas d'un compilateur qui enfreint quelque chose d'aussi simple que celui-ci (qui est réellement utilisé).



9
votes

Ils sont garantis de retourner 0 ou 1 .

Référence:
C99 STANDARD: 6.5.9 Opérateurs d'égalité

paragraphe 3:

Le == (égal à) et! = (pas égal à) les opérateurs sont analogues au rapport relationnel opérateurs sauf leur prime inférieur.108) chacun des opérateurs donne 1 si le La relation spécifiée est vraie et 0 si elle est fausse. Le résultat a le type INT. Pour n'importe quelle paire de opérandes, exactement l'une des relations est vraie.


1 commentaires

Si le compilateur est non standard conforme, il peut s'agir d'une valeur de retour mais des mandats standard Les valeurs doivent être 0 ou 1 et les implémentations de compilateur doivent adhérer à quels mandats standard.



3
votes

Autant que je puisse trouver, c'est de 6,5,9 paragraphe 3 en C99 Standard

Le == (égal à) et! = (pas égal à) Les opérateurs sont analogues à la opérateurs relationnels sauf leur priorité inférieure.108) chacun des les opérateurs donne 1 si la relation spécifiée est vraie et 0 si elle c'est faux. Le résultat a type INT. Pour toute paire d'opérandes, exactement L'une des relations est vraie.

Par conséquent, Il semble que Les valeurs évaluées doivent être 1 ou 0


0 commentaires

3
votes

Par spécification, à considérer le langage C, les opérateurs conditionnels doivent renvoyer 0 pour FALSE et 1 pour true.

en haïku formulaire: P>

Specification
Disallows this behavior,
Otherwise not C.


0 commentaires

2
votes

Avant C89 / C90 / ANSI-C, les opérateurs de comparaison ont été garantis pour produire une valeur zéro sur une condition "false" et non égale à zéro autrement. Le substitut 1 pour true "standardisation" introduit par C89 est rarement nécessaire, et dans les cas où il est nécessaire, on pourrait utiliser a = (b == c)? 1: 0; .


2 commentaires

Je ne suis pas sûr qu'il a raison de dire que "le substitut 1 pour vrai " standardisation "" a été introduit par C89. L'édition de 1978 de K & R indique clairement le 0 / 1 comportement des opérateurs relationnels et d'égalité. Je suppose que (et c'est vraiment juste une supposition) que cette spécification était suivie plus souvent que non. Il est certainement possible qu'il soit quelque peu commun de ne pas le suivre, mais la règle n'était pas nouvelle à C89.


Aurait pu évoluer la pratique. Je pense que nous avons encore K & R1 au travail quelque part. (Mais IIRC K & R1 n'a jamais dicté une "standard"; il ne décrit qu'une langue) je vais essayer de vérifier lundi. K & R2 Quelque peu d'angle C89 / C90, mais le livre que je me souvienne avait un badge "caractéristiques ansi c" sur la couverture. Aurait pu être une réimpression de la 2e édition.



4
votes

Je ne pense pas que les gens ici répondent à la question. La question était pas à propos de ce que la norme dit, la question portait sur la question s'il existe des compilateurs notables qui n'obéissent pas à la norme à cet égard.

Non, autant que je sache, il n'y a pas.


4 commentaires

+1 Selon peu importe ce que la norme dit, il y a toujours une personne qui ne suit pas à 100% à 100%, vient de regarder CSS. Mais oui, j'espère que personne ne violera une telle chose aussi simple que cela.


Oui, comme je l'ai dit. K & R C (avant l'ANSI) n'avait aucune limitation de la gamme de valeurs produites par des opérateurs de comparaison (à part "Faux == zéro")


@wildplasser: Et pas sans raison. Un opérateur relationnel peut être plus rapide s'il suffit de revenir non-zéro contre de définir la valeur toujours à une. C'est pourquoi je n'ai pas trouvé totalement impossible pour les compilateurs hérités des microcontrôleurs bas de gamme de prendre ce raccourci.


Je ne pense pas que "plus rapide" était un objectif. Il y a toujours la règle "comme si", et dans la plupart des cas, la valeur booléenne n'est utilisée que pour sa valeur de vérité (donc la règle "comme si" s'applique). L'utilisation de valeurs booléennes dans les expressions arithmétiques est très rare et un opérateur ternaire sera beaucoup plus explicite dans ce cas. Je ne sais pas quelle est la justification exacte de la décision C89 était probablement quelque chose de vague comme «ranger» ou «rester aligné avec C ++».