J'ai vu les définitions de macro suivantes dans un livre de codage.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Il n'y avait aucune explication.
S'il vous plaît me expliquer comment ceux - ci fonctionnent comme TRUE
et FALSE
.
J'ai vu les définitions de macro suivantes dans un livre de codage.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Il n'y avait aucune explication.
S'il vous plaît me expliquer comment ceux - ci fonctionnent comme TRUE
et FALSE
.
Réponses:
Voyons voir: '/' / '/'
signifie le char
littéral /
, divisé par le char
littéral '/'
lui-même. Le résultat est un, ce qui semble raisonnable TRUE
.
Et '-' - '-'
signifie le char
littéral '-'
, soustrait de lui-même. C'est zéro ( FALSE
).
Il y a deux problèmes avec cela: d'abord, ce n'est pas lisible. Utilisation 1
et 0
est absolument mieux. De plus, comme TartanLlama et KerrekSB l'ont souligné, si vous prévoyez d'utiliser cette définition, veuillez ajouter des parenthèses autour d'eux afin de ne pas avoir de surprise:
#include <stdio.h>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
printf ("%d\n", 2 * FALSE);
return 0;
}
Cela affichera la valeur du char
littéral '-'
(45 sur mon système).
Avec des parenthèses:
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
le programme imprime correctement zéro, même si cela n'a pas beaucoup de sens de multiplier une valeur de vérité par un entier, mais ce n'est qu'un exemple du genre de bogues inattendus qui pourraient vous mordre si vous ne mettez pas vos macros entre parenthèses.
if
au lieu de le multiplier TRUE
par un entier.
notx = TRUE- x;
et à mesure . Sauf que TRUE-FALSE
c'est -44 (en supposant ASCII)
C'est juste une autre façon d'écrire
#define TRUE 1
#define FALSE 0
L'expression '/'/'/'
divisera la valeur char de '/'
elle-même, ce qui donnera 1 comme résultat.
L'expression '-'-'-'
va soustraire la valeur char de '-'
d'elle-même, ce qui donnera 0 comme résultat.
Les crochets autour des define
expressions entières manquent cependant, ce qui peut entraîner des erreurs dans le code à l'aide de ces macros. La réponse de Jay répond assez bien à cela.
Un exemple de scénario "réel" où l'oubli des crochets peut être nuisible est l'utilisation combinée de ces macros avec un opérateur de cast de style C. Si quelqu'un décide de convertir ces expressions bool
en C ++ par exemple:
#include <iostream>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
std::cout << "True: " << (bool) TRUE << std::endl;
std::cout << "False: " << (bool) FALSE << std::endl;
return 0;
}
Voici ce que nous obtenons:
True: 0
False: -44
Donc (bool) TRUE
, évaluerait réellement false
et (bool) FALSE
évaluerait true
.
Cela équivaut à écrire
#define TRUE 1
#define FALSE 0
Ce que '/'/'/'
fait réellement l'expression, c'est diviser le caractère /
(quelle que soit sa valeur numérique) par lui-même, il devient donc 1
.
De même, l'expression '-'-'-'
soustrait le caractère -
de lui-même et évalue à 0
.
Il vaudrait mieux écrire
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
pour éviter un changement accidentel des valeurs lorsqu'il est utilisé avec d'autres opérateurs de priorité supérieure.
Jay a déjà répondu pourquoi les valeurs de ces expressions sont 0
et 1
.
Par souci d'histoire, ces expressions '/'/'/'
et '-'-'-'
proviennent d'une des entrées du 1er Concours International de Code C Obfuscated en 1984 :
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
(Lien vers le programme ici , il y a un indice de ce que fait ce programme dans la page IOCCC ci-dessus.)
Aussi, si je me souviens bien, ces expressions étaient des macros obscurcies TRUE
et FALSE
étaient également couvertes dans le livre "Obfuscated C and Other Mysteries" de Don Libes (1993).
C'est une façon hilarante d'écrire des macros pour True
et False
.
Comme de nombreuses explications ont été fournies, cela /
signifie qu'un nombre de 1 octet (selon ASCII) lorsqu'il est divisé par lui-même, il vous donne 1
qui sera traité comme True
et -
est également à nouveau un nombre d'octets lorsqu'il est soustrait de la même valeur qu'il vous donne 0
qui sera interprétée commefalse
#define TRUE '/'/'/'
#define FALSE '-'-'-'
par conséquent, nous pouvons remplacer /
ou -
avec n'importe quel caractère que nous aimons, par exemple:
#define TRUE '!'/'!'
#define FALSE 'o'-'o'
Gardera la même signification que l'expression originale.
Commençons par vrai. Vous pouvez le lire comme '/' / '/'
, ce qui signifie "caractère '/' divisé par caractère '/'". Étant donné que chaque caractère, en C, est une valeur numérique (sur un octet), il peut être lu comme "la valeur ASCII du caractère '/' divisé par la valeur ASCII de ce même caractère", ce qui signifie 1 (car, évidemment, x / x est 1). Par conséquent, TRUE
est 1.
Pour FALSE
, c'est le même raisonnement: '-'-'-'
lit '-' - '-'
, c'est-à-dire "la valeur ASCII de '-' moins la valeur ASCII de '-'", qui est 0. Par conséquent, FALSE
est 0.
C'est une mauvaise façon de dire l'évidence.
'/'/'/'
est 1 pour tout jeu de caractères valide, que ce soit '/' == 47
(comme c'est en ASCII), ou '/' == 97
(comme c'est en EBCDIC), ou toute autre valeur.
'/'
à 0
. Cette valeur est réservée au caractère nul.