Ich habe die folgenden Makrodefinitionen in einem Codierungsbuch gesehen.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Da gab es keine Erklärung.
Bitte erklären Sie mir, wie diese als TRUE
und funktionieren FALSE
.
Ich habe die folgenden Makrodefinitionen in einem Codierungsbuch gesehen.
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Da gab es keine Erklärung.
Bitte erklären Sie mir, wie diese als TRUE
und funktionieren FALSE
.
Antworten:
Mal sehen: '/' / '/'
bedeutet das char
Literal /
, geteilt durch das char
Literal '/'
selbst. Das Ergebnis ist eines, für das es vernünftig klingt TRUE
.
Und '-' - '-'
bedeutet die char
wörtliche '-'
, von sich selbst subtrahiert. Dies ist Null ( FALSE
).
Hier gibt es zwei Probleme: Erstens ist es nicht lesbar. Verwenden 1
und 0
ist absolut besser. Wie TartanLlama und KerrekSB bereits betont haben, sollten Sie diese Definition in Klammern setzen, damit Sie keine Überraschungen erleben:
#include <stdio.h>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
printf ("%d\n", 2 * FALSE);
return 0;
}
Dadurch wird der Wert des char
Literal gedruckt '-'
(45 auf meinem System).
Mit Klammern:
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
Das Programm gibt Null korrekt aus, obwohl es wenig sinnvoll ist, einen Wahrheitswert mit einer Ganzzahl zu multiplizieren. Es ist jedoch nur ein Beispiel für unerwartete Fehler, die Sie beißen können, wenn Sie Ihre Makros nicht in Klammern setzen.
if
anstatt TRUE
mit einer ganzen Zahl zu multiplizieren .
notx = TRUE- x;
und funktioniert einwandfrei. Nur dass TRUE-FALSE
das -44 ist (unter der Annahme von ASCII)
Es ist nur eine andere Art zu schreiben
#define TRUE 1
#define FALSE 0
Der Ausdruck '/'/'/'
teilt den Zeichenwert von '/'
durch sich selbst, was als Ergebnis 1 ergibt.
Der Ausdruck '-'-'-'
subtrahiert den Zeichenwert '-'
von sich selbst, was als Ergebnis 0 ergibt.
Es define
fehlen jedoch Klammern um die gesamten Ausdrücke, was zu Fehlern im Code führen kann, wenn diese Makros verwendet werden. Jays Antwort spricht das ziemlich gut an.
Ein Beispiel für ein "reales" Szenario, in dem das Vergessen der Klammern schädlich sein kann, ist die kombinierte Verwendung dieser Makros mit einem C-ähnlichen Cast-Operator. Wenn sich jemand entscheidet, diese Ausdrücke bool
in C ++ umzuwandeln, zum Beispiel:
#include <iostream>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
std::cout << "True: " << (bool) TRUE << std::endl;
std::cout << "False: " << (bool) FALSE << std::endl;
return 0;
}
Folgendes bekommen wir:
True: 0
False: -44
So (bool) TRUE
würde bewerten tatsächlich zu false
, und (bool) FALSE
würde evaluieren true
.
Es ist gleichbedeutend mit Schreiben
#define TRUE 1
#define FALSE 0
Was der Ausdruck '/'/'/'
tatsächlich tut, ist das Teilen des Zeichens /
(unabhängig von seinem numerischen Wert) durch sich selbst, so dass es wird 1
.
In ähnlicher Weise '-'-'-'
subtrahiert der Ausdruck das Zeichen -
von sich selbst und wertet es aus 0
.
Es wäre besser zu schreiben
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
um versehentliche Änderungen von Werten bei Verwendung mit anderen Operatoren mit höherer Priorität zu vermeiden.
Jay hat bereits geantwortet, warum die Werte dieser Ausdrücke 0
und sind 1
.
Zur Geschichte willen, diese Ausdrücke '/'/'/'
und '-'-'-'
von einem der Einträge kommen 1st International Obfuscated C - Code Contest 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);}
(Link zum Programm hier , es gibt einen Hinweis darauf, was dieses Programm auf der IOCCC-Seite oben tut.)
Auch wenn ich mich richtig erinnere, wurden diese Ausdrücke als verschleierte Makros für TRUE
und FALSE
wurden auch in dem Buch "Obfuscated C and Other Mysteries" von Don Libes (1993) behandelt.
Es ist eine lustige Art, Makros für True
und zu schreiben False
.
Da viele Erklärungen gegeben wurden, /
bedeutet dies, dass eine 1-Byte-Zahl (gemäß ASCII), wenn sie durch sich selbst geteilt wird, 1
die als behandelt wird, True
und ebenfalls -
eine Byte-Zahl ist, wenn derselbe Wert subtrahiert wird, den Sie erhalten, 0
der als interpretiert wirdfalse
#define TRUE '/'/'/'
#define FALSE '-'-'-'
Daher können wir /
oder -
durch ein beliebiges Zeichen ersetzen , zum Beispiel:
#define TRUE '!'/'!'
#define FALSE 'o'-'o'
Behält die gleiche Bedeutung wie der ursprüngliche Ausdruck.
Beginnen wir mit true. Sie können es als lesen '/' / '/'
, was "Zeichen '/' geteilt durch Zeichen '/'" bedeutet. Da jedes Zeichen in C ein numerischer Wert (auf einem Byte) ist, kann es als "der ASCII-Wert des Zeichens '/' geteilt durch den ASCII-Wert desselben Zeichens" gelesen werden, was 1 bedeutet (weil offensichtlich x / x ist 1). Daher TRUE
ist 1.
Denn es FALSE
ist die gleiche Argumentation:'-'-'-'
liest '-' - '-'
, dh "der ASCII-Wert von '-' minus dem ASCII-Wert von '-'", der 0 ist. Daher FALSE
ist 0.
Dies ist eine böse Art, das Offensichtliche zu sagen.
'/'/'/'
ist 1 für jeden gültigen Zeichensatz, egal ob '/' == 47
(wie in ASCII) oder '/' == 97
(wie in EBCDIC) oder für einen anderen Wert.
'/'
zu 0
. Dieser Wert ist für das Nullzeichen reserviert.