2010-08-20 18 views
8

Est-ce que les instructions conditionnelles C retournent toujours [1 ou 0] ou retournent-elles [0 ou "autre chose que zéro"]. Je demande parce que:Un C conditionnel retournera-t-il toujours 1 ou 0?

code pseudo -

foo (adresse, shouldSend):
registre >> = 1
registre < < = 1 // pour effacer bit en première position
registre | = shouldSend // pour indiquer si elle doit envoyer ou non

le problème se produit si quelqu'un passe dans une valeur de shouldSend de true supérieur à un (car seulement 0 est false et tout le reste est vrai, techniquement c'est valide). puisque je suis directement OR'ing la valeur de vérité de shouldSend avec le registre, il vaut mieux ne pas dire 0xFF! J'ai déjà une solution, donc la question est plus par curiosité. Je me demande cependant si:

foo (adresse, shouldSend):
registre >> = 1
registre < < = 1 // pour effacer bit en première position
registre | = (shouldSend> 0)// pour signaler si elle doit envoyer ou non

résout le problème? Je pense que maintenant le problème d'un 0xFF (ou en général, quelque chose de plus grand que 1) passé est masqué par le conditionnel C. mais cela ne tient que si les conditionnels C C sont garantis pour retourner [0 ou 1]. Ps - je me rends également compte qu'il est probablement dépendant du compilateur, mais que dit le standard ansi à ce propos?

+0

Ce ne devrait pas être (shouldSend! = 0)? En utilisant !! shouldSend est un mauvais tour. –

Répondre

16

standard indique que le résultat est toujours une valeur entier est égal à 0 ou 1

6.5.8 opérateurs relationnels

chacun des opérateurs < (inférieur à),> (supérieure à), < = (inférieur ou égal à à), et> = (supérieur ou égal à) doit donner 1 si la relation spécifiée est vraie et 0 si elle est false.92) Le résultat est type int.

+0

+1, assez surprenant qu'il spécifie effectivement ce comportement. Au fil du temps, je suppose que la spécification serait plus susceptible de dire "retourne 0 ou au hasard des dés" – JaredPar

+0

Oui, le standard est parfaitement clair à ce sujet. –

+1

Cela conduit à l'idiome que j'ai vu utilisé depuis avant il y avait un standard: '!! somevalue' qui a la même valeur de vérité, mais qui est maintenant garanti être exactement 0 ou 1. – RBerteig

1

Peu importe si cela est spécifié ou non. Il est préférable de toujours tester contre false et d'être explicite sur vos valeurs égales ou égales. Cela supprime tout souci concernant les implémentations du compilateur et est plus clair et plus facile à maintenir.

+0

C'est en fait pertinent, puisque vous pourriez utiliser & et | opérateurs comme opérateurs logiques SANS court-circuit. – Spidey

1

Plutôt que de droite à gauche et décalage de décalage à nouveau pour effacer le bit de poids faible, je logique binaire avec 0xFE:

register = register & 0xFE; 

[edit: registre en supposant est 8 bits. Sinon, adaptez l'opérande de droite si nécessaire]

Mais oui, si shouldSend est le résultat d'un test conditionnel, il est garanti que le standard est 0 ou 1.S'il y a un doute quant à savoir si shouldSend pourrait être générée à partir nulle part ailleurs, il serait sage de mettre dans le genre de précaution que vous avez, ou quelque chose comme

register = register | (shouldSend ? 1 : 0); 
+1

L'idiome que j'ai vu utilisé avant il y avait un standard: '!! somevalue' qui a la même valeur de vérité, mais qui est maintenant garanti être exactement 0 ou 1. – RBerteig

+0

@RBerteig: Nice! – Vicky

0

Oui. Ceci est garanti en C99. Je n'ai pas la spécification C89 à portée de main. Bien sûr, les implémenteurs de compilateurs ont été connus pour faire des erreurs à l'occasion, donc YMMV.

C99 indique ce qui suit au paragraphe 6 de 6.5.8 opérateurs relationnels:

chacun des opérateurs < (inférieur), > (supérieur à), < = (inférieur ou égal à), et > = (supérieur ou égal à) doit donner 1 si la relation spécifiée est vraie et 0 si elle est fausse.

Les mêmes ou clauses similaires figurent au paragraphe 3 de 6.5.9 opérateurs égalité, paragraphe 3 de 6.5.13 opérateur AND logique et le paragraphe 3 de 6.5.14 logique opérateur OR.

+0

Cela était vrai dans le K & R C d'origine et dépendait souvent, de sorte que les normes devaient suivre. – RBerteig