Ich denke, es ist nur eine lustige Art, TRUE als 1 und FALSE als 0 zu definieren
BlackDwarf
160
Beachten Sie, dass dies eine schreckliche Idee ohne Klammern um diese Ausdrücke ist. Ich meine, es ist eine schreckliche Idee mit ihnen, aber ohne dass Sie nur nach einer langen Nacht des Debuggens fragen.
TartanLlama
70
Darf ich das Codierungsbuch kennen, auf das Sie sich beziehen?
Artm
47
Ich hoffe, dass das Buch dies als Beispiel für schlechten oder absichtlich undurchsichtigen Code enthält.
Jon Hanna
31
@ Daniel: Eine andere Idee wäre, rand ()% 2 MAYBE als rand ()% 2 zu definieren, das ist also manchmal == TRUE und manchmal == FALSE.
Kaiserludi
Antworten:
380
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:
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.
Verdammt, ich habe viel gebraucht, um es zu verstehen: Ich dachte sogar, es wäre eine seltsame Sache als Glyphen ... weiß nicht xD
Luis Masuelli
8
Es ist tatsächlich sinnvoll, mit dem Wahrheitswert zu multiplizieren. Zum Beispiel führt ein Einzug * should_indent entweder zu 0 oder zu einem Einzug, je nachdem, ob should_indent ohne Verzweigung ist. (Ich denke, dass dies ein schlechtes Beispiel ist, wenn die Arbeit mit einer einzelnen Verzweigung von Text keine Rolle spielt (ich habe diese Technik in Shadern und in XPATH gesehen (beide zu unterschiedlich und ich erinnere mich nicht an die genaue Form))
Alpedar
2
Alpedar - aber es macht konzeptionell und matehmatisch keinen Sinn, dies zu tun - in diesem Fall wäre es klarer (und konzeptionell sinnvoll), eine zu verwenden, ifanstatt TRUEmit einer ganzen Zahl zu multiplizieren .
Jay
4
Tolle Erklärung. Habe ein goldenes Abzeichen!
Michael Hampton
2
Die logische Negation kann als implementiert werden notx = TRUE- x;und funktioniert einwandfrei. Nur dass TRUE-FALSEdas -44 ist (unter der Annahme von ASCII)
Hagen von Eitzen
89
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:
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.
@ Fabien: Es hängt nicht von ASCII ab. '/'/'/'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.
Keith Thompson
4
@Pawel: Eine konforme C - Implementierung kann nicht zuordnen '/'zu 0. Dieser Wert ist für das Nullzeichen reserviert.
Keith Thompson
2
Du bist pedantisch.
Matheus208
3
@ Matheus208 Wenn Pawel pedantisch war, dann ist das ('-'-'-'), da sein Standpunkt auf einem nicht angegebenen Zustand beruhte; Keith 'Äußerungen als pedantisch zu beschreiben, mag mehr sein (' / '/' / '), aber ich würde sie "klarstellend" nennen (und mit den hinzugefügten Smileys scheint "pedantisch" mir definitiv' / '-' / 'zu sein). Es mag sein ('-' / '-'), dass die Kommentare zusammengenommen als pedantisch bezeichnet werden können, aber 1) ist das in diesem Bereich nicht etwas obligatorisch? 2) sie haben mich zum Nachdenken gebracht; und 3) Ich bin in einigen Dingen etwas klarer als ich. Und ja, ich glaube, ich bin selbst pedantisch! (Aber ich bin klarer darüber, was "pedantisch" bedeutet als ich! ;-)
Antworten:
Mal sehen:
'/' / '/'
bedeutet daschar
Literal/
, geteilt durch daschar
Literal'/'
selbst. Das Ergebnis ist eines, für das es vernünftig klingtTRUE
.Und
'-' - '-'
bedeutet diechar
wörtliche'-'
, von sich selbst subtrahiert. Dies ist Null (FALSE
).Hier gibt es zwei Probleme: Erstens ist es nicht lesbar. Verwenden
1
und0
ist absolut besser. Wie TartanLlama und KerrekSB bereits betont haben, sollten Sie diese Definition in Klammern setzen, damit Sie keine Überraschungen erleben:Dadurch wird der Wert des
char
Literal gedruckt'-'
(45 auf meinem System).Mit Klammern:
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.
quelle
if
anstattTRUE
mit einer ganzen Zahl zu multiplizieren .notx = TRUE- x;
und funktioniert einwandfrei. Nur dassTRUE-FALSE
das -44 ist (unter der Annahme von ASCII)Es ist nur eine andere Art zu schreiben
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:Folgendes bekommen wir:
So
(bool) TRUE
würde bewerten tatsächlich zufalse
, und(bool) FALSE
würde evaluierentrue
.quelle
Es ist gleichbedeutend mit Schreiben
Was der Ausdruck
'/'/'/'
tatsächlich tut, ist das Teilen des Zeichens/
(unabhängig von seinem numerischen Wert) durch sich selbst, so dass es wird1
.In ähnlicher Weise
'-'-'-'
subtrahiert der Ausdruck das Zeichen-
von sich selbst und wertet es aus0
.Es wäre besser zu schreiben
um versehentliche Änderungen von Werten bei Verwendung mit anderen Operatoren mit höherer Priorität zu vermeiden.
quelle
Jay hat bereits geantwortet, warum die Werte dieser Ausdrücke
0
und sind1
.Zur Geschichte willen, diese Ausdrücke
'/'/'/'
und'-'-'-'
von einem der Einträge kommen 1st International Obfuscated C - Code Contest 1984 :(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
undFALSE
wurden auch in dem Buch "Obfuscated C and Other Mysteries" von Don Libes (1993) behandelt.quelle
Es ist eine lustige Art, Makros für
True
und zu schreibenFalse
.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
Daher können wir
/
oder-
durch ein beliebiges Zeichen ersetzen , zum Beispiel:Behält die gleiche Bedeutung wie der ursprüngliche Ausdruck.
quelle
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). DaherTRUE
ist 1.Denn es
FALSE
ist die gleiche Argumentation:'-'-'-'
liest'-' - '-'
, dh "der ASCII-Wert von '-' minus dem ASCII-Wert von '-'", der 0 ist. DaherFALSE
ist 0.Dies ist eine böse Art, das Offensichtliche zu sagen.
quelle
'/'/'/'
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.'/'
zu0
. Dieser Wert ist für das Nullzeichen reserviert.