web-dev-qa-db-fra.com

Étranges définitions des macros 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 là.

Expliquez-moi comment ils fonctionneront comme TRUE et FALSE.

297
Keshava GN

Voyons: '/' / '/' signifie le char littéral /, divisé par le char littéral '/' lui-même. Le résultat est un, ce qui semble raisonnable pour TRUE.

Et '-' - '-' signifie le char littéral '-', soustrait de lui-même. C'est zéro (FALSE).

Cela pose deux problèmes: premièrement, ce n'est pas lisible. Utiliser 1 et 0 est absolument préférable. De plus, comme l'ont souligné TartanLlama et KerrekSB, si vous utilisez cette définition, ajoutez des parenthèses autour de la définition afin d'éviter toute surprise:

#include <stdio.h>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

int main() {
        printf ("%d\n", 2 * FALSE);
        return 0;
}

Ceci affichera la valeur de char littéral '-' (45 sur mon système).

Avec des parenthèses:

#define TRUE  ('/'/'/')
#define FALSE ('-'-'-')

le programme affiche correctement zéro, même s'il est insensé de multiplier une valeur de vérité par un entier, mais il ne s'agit que d'un exemple du type de bogues inattendus qui pourraient vous piquer si vous ne parentzez pas vos macros.

377
Jay

C'est juste une autre façon d'écrire

#define TRUE 1
#define FALSE 0

L'expression '/'/'/' divisera la valeur de caractère de '/' par elle-même, ce qui donnera 1 comme résultat.

L'expression '-'-'-' soustraira de lui-même la valeur de caractère '-', ce qui donnera 0 comme résultat.

Des crochets entourant l'ensemble des expressions define manquent cependant, ce qui peut entraîner des erreurs dans le code utilisant ces macros. La réponse de Jay adresse assez bien ça.

Un exemple de scénario "réel" dans lequel oublier les crochets peut être préjudiciable est l’utilisation combinée de ces macros avec un opérateur de conversion de style C. Si quelqu'un décide de convertir ces expressions en 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

Ainsi, (bool) TRUE serait évalué à false, et (bool) FALSE serait évalué à true.

88
BlackDwarf

Cela équivaut à écrire

#define TRUE 1
#define FALSE 0

En réalité, l'expression '/'/'/' divise le caractère / (quelle que soit sa valeur numérique) par lui-même, de sorte qu'il devient 1.

De même, l'expression '-'-'-' soustrait le caractère - de lui-même et est évaluée à 0.

Il vaudrait mieux écrire

#define TRUE ('/'/'/')
#define FALSE ('-'-'-')

pour éviter toute modification accidentelle des valeurs lorsqu’il est utilisé avec d’autres opérateurs de priorité supérieure.

44
0605002

Jay a déjà expliqué pourquoi les valeurs de ces expressions sont 0 et 1.

Pour des raisons d’histoire, ces expressions '/'/'/' et '-'-'-' proviennent d’une des entrées du 1er concours international de code C dissimulé 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 une indication de ce que fait ce programme dans la page IOCCC ci-dessus.)

De plus, si je me souviens bien de ces expressions en tant que macros obscurcies pour TRUE et FALSE, elles étaient également couvertes dans "Céfacts et autres mystères" livre de Don Libes (1993).

32
ouah

C'est une manière hilarante d'écrire des macros pour True et False.

Comme de nombreuses explications ont été fournies / signifie un nombre à 1 octet (selon ASCII) lorsqu'il est divisé par lui-même, il vous donne 1 qui sera traité comme True et de même - est encore un nombre d’octets quand on soustrait la même valeur cela vous donne 0 qui sera interprété comme false

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

par conséquent, nous pouvons remplacer / ou - par n'importe quel caractère de notre choix, par exemple:

#define TRUE  '!'/'!'
#define FALSE 'o'-'o'

Gardera le même sens que l'expression originale.

7
anand

Commençons par vrai. Vous pouvez le lire sous la forme '/' / '/', ce qui signifie "caractère"/"divisé par le caractère"/"". Comme 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ée par la valeur ASCII de ce dernier. same character ", ce qui signifie 1 (car, évidemment, x/x est 1). Par conséquent, TRUE vaut 1.

Pour FALSE, son raisonnement est le même: '-'-'-' lit '-' - '-', c'est-à-dire "la valeur ASCII de '-' moins la valeur ASCII de '-' ", qui vaut 0. Par conséquent, FALSE vaut 0.

C’est un mauvais moyen d’énoncer une évidence.

6
Fabien