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 TRUEund 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 TRUEund funktionieren FALSE.
Antworten:
Mal sehen: '/' / '/'bedeutet das charLiteral /, geteilt durch das charLiteral '/'selbst. Das Ergebnis ist eines, für das es vernünftig klingt TRUE.
Und '-' - '-'bedeutet die charwörtliche '-', von sich selbst subtrahiert. Dies ist Null ( FALSE).
Hier gibt es zwei Probleme: Erstens ist es nicht lesbar. Verwenden 1und 0ist 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 charLiteral 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.
ifanstatt TRUEmit einer ganzen Zahl zu multiplizieren .
notx = TRUE- x;und funktioniert einwandfrei. Nur dass TRUE-FALSEdas -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 definefehlen 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 boolin 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) TRUEwürde bewerten tatsächlich zu false, und (bool) FALSEwü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 0und 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 TRUEund FALSEwurden auch in dem Buch "Obfuscated C and Other Mysteries" von Don Libes (1993) behandelt.
Es ist eine lustige Art, Makros für Trueund 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, 1die als behandelt wird, Trueund ebenfalls -eine Byte-Zahl ist, wenn derselbe Wert subtrahiert wird, den Sie erhalten, 0der 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 TRUEist 1.
Denn es FALSEist die gleiche Argumentation:'-'-'-' liest '-' - '-', dh "der ASCII-Wert von '-' minus dem ASCII-Wert von '-'", der 0 ist. Daher FALSEist 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.