Pourquoi les #define TRUE (1==1) dans un C boolean macro au lieu de simplement 1?
J'ai vu des définitions en C
#define TRUE (1==1)
#define FALSE (!TRUE)
Est-ce nécessaire? Quel est l'avantage par rapport à la simple définition VRAI que 1, et FAUX que 0?
- Et plus:
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(prises à partir de coding-guidelines.com/cbook/cbook1_1.pdf page 871) - Non, c'est de la paranoïa par le paumé^Wunderinformed, vraiment. En C, 1 et 0 faire en toutes circonstances, la même.
- Ça veut dire quoi?
Vous devez vous connecter pour publier un commentaire.
Cette approche permettra d'utiliser le
boolean
type (et de résoudre àtrue
etfalse
) si le compilateur prend en charge. (plus précisément, C++)Cependant, il serait préférable de vérifier si le C++ est en cours d'utilisation (par l'intermédiaire de la
__cplusplus
macro) et de réellement utilisertrue
etfalse
.Dans un compilateur C, c'est l'équivalent de
0
et1
.(notez que la suppression des parenthèses peut briser ce en raison de l'ordre des opérations)
1==1
est unint
. (voir stackoverflow.com/questions/7687403/... .)boolean
type?true
oufalse
.#define TRUE true
et#define FALSE false
chaque fois que__cplusplus
est défini.La réponse est la portabilité. Les valeurs numériques de
TRUE
etFALSE
ne sont pas importantes. Ce est important est qu'un énoncé commeif (1 < 2)
évalue àif (TRUE)
et une déclaration commeif (1 > 2)
évalue àif (FALSE)
.Accordée, dans C,
(1 < 2)
évalue à1
et(1 > 2)
évalue à0
, alors que d'autres l'ont dit, il n'y a pas de différence pratique autant que le compilateur est concerné. Mais en laissant le compilateur définirTRUE
etFALSE
selon ses propres règles, vous êtes en rendant leurs significations explicites pour les programmeurs, et vous êtes garantir la cohérence au sein de votre programme et de toute autre bibliothèque (en supposant que l'autre bibliothèque suit normes C ... vous seriez étonné de voir).Un Peu D'Histoire
Quelques notions de base défini
FALSE
comme0
etTRUE
comme-1
. Comme beaucoup de langues modernes, ils interprété une valeur non nulle, commeTRUE
, mais ils évalué des expressions booléennes qui était vrai que-1
. LeurNOT
opération a été mise en œuvre par l'ajout de 1 et le retournement de la signer, parce que c'était efficace pour le faire de cette façon. Si "PAS de x" est devenu-(x+1)
. Un effet secondaire de ceci est qu'une valeur comme5
évalue àTRUE
, maisNOT 5
évalue à-6
, qui est aussiTRUE
! Trouver ce genre de bug n'est pas amusant.Meilleures Pratiques
Compte tenu de la de facto règles que zéro est interprété comme
FALSE
et tout valeur non nulle est interprété commeTRUE
, vous devriez jamais booléen-à la recherche des expressions pourTRUE
ouFALSE
. Exemples:Pourquoi? Parce que beaucoup de programmeurs utilisent le raccourci de traitement de
int
s commebool
s. Ils ne sont pas les mêmes, mais les compilateurs permettent généralement il. Ainsi, par exemple, il est parfaitement légal d'écrireQue semble légitime, et le compilateur sera heureux de l'accepter, mais il n'a probablement pas faire ce que vous voulez. C'est parce que la valeur de retour de
strcmp()
est0 si
yourString == myString
<0 si
yourString < myString
>0 si
yourString > myString
De sorte que la ligne ci-dessus renvoie
TRUE
uniquement lorsqueyourString > myString
.La bonne façon de le faire est soit
ou
De la même façon:
Vous trouverez souvent, certains de ces "mauvais exemples" dans le code de production, et de nombreux programmeurs expérimentés ne jurent que par eux: ils travaillent, certains sont plus courtes que celles de leur (de manière affectée?) corriger des solutions de rechange, et les expressions idiomatiques sont presque universellement reconnu. Mais pensez-y: le "droit" des versions ne sont pas moins efficaces, ils sont garantis pour être portable, ils passent même la plus stricte linters, et même de nouveaux programmeurs vont comprendre.
N'est pas la peine?
(1==1)
n'est pas plus portable que les1
. Le compilateur propres règles sont celles du langage C, qui est clair et sans ambiguïté sur la sémantique de l'égalité et des opérateurs relationnels. Je n'ai jamais vu un compilateur obtenir ce genre de choses de mal.strcmp
est connu pour être inférieure, égale ou supérieure à 0. Il n'est pas garanti d'être -1, 0 ou 1 et il y a des plates-formes dans la nature qui n'est pas le retour de ces valeurs pour gagner de la vitesse de mise en œuvre. Donc, sistrcmp(a, b) == TRUE
puisa > b
mais inverse implication pourrait pas tenir.(1==1)
et1
sont à la fois des expressions constantes de typeint
avec la valeur 1. Ils sont sémantiquement identiques. Je suppose que vous pouvez écrire du code qui s'adresse à des lecteurs qui ne le savent pas, mais où prend-elle fin?TRUE
certainement est important. C'est une partie cruciale de l'algèbre booléenne, qui définit de cette façon à garder une bonne correspondance entre les opérations booléennes et entier.La
(1 == 1)
astuce est utile pour la définition desTRUE
dans une manière qui est transparent pour le C, fournit encore mieux taper en C++. Le même code peut être interprété comme C ou C++ si vous avez écrit dans un dialecte appelé "Propre C" (qui compile soit en C ou C++) ou si vous êtes à la rédaction de l'API de fichiers d'en-tête qui peut être utilisé en C ou C++ programmeurs.Dans C les unités de traduction,
1 == 1
a exactement le même sens que1
; et1 == 0
a le même sens que0
. Toutefois, dans le C++ unités de traduction,1 == 1
a typebool
. Ainsi, leTRUE
macro définie de cette façon, s'intègre de mieux en C++.Un exemple de la façon dont il s'intègre mieux, c'est que par exemple si la fonction
foo
a surcharges pourint
et pourbool
, puisfoo(TRUE)
sera de choisir lebool
de surcharge. SiTRUE
est simplement défini comme1
, alors il ne fonctionne pas bien dans le C++.foo(TRUE)
voulez leint
surcharge.Bien sûr, C99 introduit
bool
,true
, etfalse
et ceux-ci peuvent être utilisés dans les fichiers d'en-tête que le travail avec le C99 et avec C.Cependant:
TRUE
etFALSE
comme(0==0)
et(1==0)
est antérieure à C99.Si vous travaillez dans un mélange de C et de C++ du projet, et ne veulent pas C99, de définir les bas-de-casse
true
,false
etbool
à la place.Cela étant dit, le
0==0
truc, c'était (est?) utilisé par certains programmeurs, même dans le code qui n'a jamais été destiné à interagir avec le C++ en aucune façon. Que ne pas acheter n'importe quoi et suggère que le programmeur a une incompréhension de la façon dont les booléens travail en C.Dans le cas où le C++ explication n'était pas claire, voici un programme de test:
La sortie:
Quant à la question à partir des commentaires de la façon dont sont surchargés C++ les fonctions pertinentes à des mélanges de programmation C et C++. Ces juste illustrer un type de différence. Une raison valable pour vouloir un
true
constante àbool
lorsqu'il est compilé comme le C++ est propre diagnostic. À son plus haut niveau d'alerte, un compilateur C++ pourrait nous mettre en garde contre une conversion si on passe un entier comme unbool
paramètre. Une des raisons de l'écriture Propre, C est pas seulement que notre code n'est plus portable (puisqu'il est compris par les compilateurs C++, non seulement les compilateurs C), mais l'on peut bénéficier de l'diagnostic opinions des compilateurs C++.TRUE
seront différents selon C++.#ifdef __cplusplus
pour exprimer votre intention beaucoup plus clairement.bool
etint
n'a pas beaucoup d'importance dans la pratique, puisqu'ils sont implicitement convertible à l'autre (et dans C en fait, "le même", notez les guillemets, tout de même) et il n'y a pas beaucoup de situations dans lesquelles vous avez vraiment besoin de disambuigate entre les deux. "pas beaucoup" a été probablement trop lourd, "beaucoup moins par rapport à code à l'aide de modèles et de surcharge" aurait été mieux peut-être.(0==0)
comme moyen approprié pour définir un "indépendant de la langue"TRUE
et je suis d'accord qu'un#ifdef __cplusplus
bloc est beaucoup plus claire. Mais néanmoins, cette macro est une façon de le faire, même si ce n'est le meilleur. La seule chose qui a suscité mon commentaire a été vous de sauter sur les fonctions surchargées exemple, alors qu'il était juste que, un exemple pour une plus inhérente et d'un problème conceptuel, la neccessity pour propery de frappe (qui vous, comme votre commentaire précédent suggère, également de haute valeur).est équivalent à
dans C.
Le résultat des opérateurs relationnels est
0
ou1
.1==1
est garanti d'être évalué pour1
et!(1==1)
est garanti d'être évalué pour0
.Il n'y a absolument aucune raison d'utiliser la première forme. Notez que la première forme est cependant pas moins efficace que sur presque tous les compilateurs une expression constante est évaluée au moment de la compilation plutôt qu'au moment de l'exécution. C'est autorisé conformément à la présente règle:
PC-Lint sera même question d'un message (506, la valeur de la constante booléenne) si vous n'utilisez pas un littéral pour
TRUE
etFALSE
macros:Également en C99, la
stdbool.h
définitions booléenne macrostrue
etfalse
utiliser directement les littéraux:1==1
va à1
au lieu d'un indéfini valeur différente de zéro?1==1
est garanti d'être évalué pour1
false
est nécessaire d'avoir une valeur spécifique, à savoir 0, alors pourquoi n'est-il pas coutume de définirfalse
comme0
ettrue
comme(!0)
?if(foo == true)
, qui va simplement de la mauvaise pratique de flat-out buggy.!
de l'opérateur.(x == TRUE)
peut avoir une valeur de vérité quex
.De côté à partir de C++ (déjà mentionné), un autre avantage est pour les outils d'analyse statique. Le compilateur va faire disparaître les inefficacités, mais un analyseur statique peut utiliser son propre résumé types de distinguer entre les résultats de la comparaison et d'autres types d'entiers, de sorte qu'il sait implicitement que le VRAI doit être le résultat d'une comparaison et ne doivent pas être pris pour être compatible avec un entier.
Évidemment C dit qu'ils sont compatibles, mais vous pouvez choisir d'interdire l'utilisation délibérée de cette fonctionnalité pour aider à mettre en évidence les bogues, par exemple, où quelqu'un peut avoir confondre
&
et&&
, ou qu'ils ont raté leur ordre de priorité des opérateurs.if (boolean_var == TRUE)
par la voie de l'expansion àif (boolean_var == (1 == 1))
qui, grâce à la meilleure info de la(1 == 1)
nœud tombe dans le modèleif (<*> == <boolean_expr>)
.La pratique de différence a pas.
0
est évalué àfalse
et1
est évalué àtrue
. Le fait que vous utilisez un expression booléenne (1 == 1
) ou1
, de définirtrue
, ne fait aucune différence. Ils ont tous les deux obtient évalué àint
.Avis que la bibliothèque C standard fournit un en-tête spécifique pour définir les booléens:
stdbool.h
.true
est évalué à1
etfalse
est évalué à0
. C ne savez pas à propos de native les types boolean, ils sont tout entiers.int
, avec la valeur0
ou1
. C t un type booléen (_Bool
, avec une macrobool
défini dans<stdbool.h>
, mais qui n'a été ajouté en C99, qui n' pas changer la sémantique des opérateurs à l'utilisation du nouveau type._Bool
, et<stdbool.h>
a#define bool _Bool
.1 == 1
en cours d'évaluation commeint
. Édité.Nous ne connaissons pas la valeur exacte que la VRAIE est égale à et les compilateurs peuvent avoir leurs propres définitions. Donc, ce que vous privode est d'utiliser le compilateur interne pour la définition. Ce n'est pas toujours nécessaire si vous avez de bonnes habitudes de programmation, mais peut éviter des problèmes pour certains mauvais style de codage, par exemple:
si ( (a > b) == TRUE)
Ce serait une catastrophe si vous mannually définir VRAI que 1, alors que la valeur TRUE est une autre.
>
opérateur donne toujours 1 pour true, 0 pour faux. Il n'y a pas de possibilité de n'importe quel compilateur C obtenir cette erreur. L'égalité des comparaisons àTRUE
etFALSE
sont style pauvres; le ci-dessus est plus clairement écrit queif (a > b)
. Mais l'idée que les différents compilateurs C peut traiter la vérité et le faux différemment, c'est tout simplement faux.Généralement dans le Langage de Programmation C, 1 est définie comme true et 0 est définie sur false. C'est pourquoi vous voyez la suite assez souvent:
Cependant, aucun numéro n'est pas égal à 0 serait évalué à vrai aussi dans une instruction conditionnelle. Par conséquent, en utilisant le ci-dessous:
Vous pouvez simplement afficher explicitement que vous avez essayé de jouer la sécurité en faisant de fausses égal à ce qui n'est pas vrai.