Seltsame Definitionen von TRUE- und FALSE-Makros

Lesezeit: 6 Minuten

Benutzeravatar von Keshava GN
Keshava GN

Ich habe die folgenden Makrodefinitionen in einem Programmierbuch gesehen.

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

Da gab es keine Erklärung.

Bitte erklären Sie mir, wie diese funktionieren TRUE und FALSE.

  • Ich denke, es ist nur eine lustige Art, TRUE als 1 und FALSE als 0 zu definieren

    – Schwarzer Zwerg

    3. Dezember 2015 um 9:47 Uhr

  • Beachten Sie, dass dies eine schreckliche Idee ohne Klammern um diese Ausdrücke ist. Ich meine, es ist eine schreckliche Idee mit sie, aber ohne dass Sie nur nach einer langen Nacht des Debuggens fragen.

    – TartanLama

    3. Dezember 2015 um 9:51 Uhr


  • Darf ich das Codierungsbuch kennen, auf das Sie sich beziehen?

    – artm

    3. Dezember 2015 um 9:54 Uhr

  • Ich hoffe, dass dieses Buch dies als Beispiel für schlechten oder absichtlich obskuren Code enthielt.

    – Jon Hanna

    3. Dezember 2015 um 10:13 Uhr

  • @Daniel: Eine andere Idee wäre, rand()%2 VIELLEICHT als rand()%2 zu definieren, so dass es manchmal == TRUE und manchmal == FALSE ist.

    – Kaiserludi

    3. Dezember 2015 um 15:24 Uhr

Benutzeravatar von Jay
Jay

Mal schauen: "https://stackoverflow.com/" / "https://stackoverflow.com/" Bedeutet die char wörtlich /geteilt durch die char wörtlich "https://stackoverflow.com/" selbst. Das Ergebnis ist eins, das sich vernünftig anhört TRUE.

Und '-' - '-' Bedeutet die char wörtlich '-', von sich selbst subtrahiert. Das ist Null (FALSE).

Dabei gibt es zwei Probleme: Erstens ist es nicht lesbar. Verwenden 1 und 0 ist absolut besser. Außerdem, wie TartanLlama und KerrekSB betont haben, wenn Sie diese Definition jemals verwenden werden, fügen Sie sie bitte in Klammern ein, damit Sie keine Überraschungen erleben:

#include <stdio.h>

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

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

Dadurch wird der Wert von gedruckt char wörtlich '-' (45 auf meinem System).

Mit Klammern:

#define TRUE  ("https://stackoverflow.com/"/"https://stackoverflow.com/")
#define FALSE ('-'-'-')

das Programm gibt korrekt Null aus, obwohl es nicht viel Sinn macht, einen Wahrheitswert mit einer ganzen Zahl zu multiplizieren, aber es ist nur ein Beispiel für die Art von unerwarteten Fehlern, die Sie beißen könnten, wenn Sie Ihre Makros nicht in Klammern setzen.

  • Es macht tatsächlich Sinn, mit dem Wahrheitswert zu multiplizieren. Zum Beispiel ergibt Einrückung*sollte_einzug entweder 0 oder Einrückung basierend darauf, ob sollte_einzug ohne Verzweigung sein soll. (Ich denke, dass dies ein schlechtes Beispiel ist, wenn mit Text gearbeitet wird, spielt eine einzelne Verzweigung keine Rolle (ich habe diese Technik in Shadern und in XPATH gesehen (beide zu unterschiedlich und ich erinnere mich nicht an die genaue Form))

    – Alpedar

    4. Dezember 2015 um 9:02 Uhr

  • Alpedar – aber das tut es nicht konzeptionell und mathematisch sinnvoll sein — in diesem Fall wäre es klarer (und konzeptionell sinnvoll), an zu verwenden if statt zu multiplizieren TRUE durch eine ganze Zahl.

    – Jay

    4. Dezember 2015 um 10:26 Uhr


  • Logische Negation könnte implementiert werden als notx = TRUE- x; und funktioniert gut. Außer dass TRUE-FALSE ist -44 (ASCII vorausgesetzt)

    – Hagen von Eitzen

    5. Dezember 2015 um 9:43 Uhr

  • @MarcWittke: Tja, wer den C-Präprozessor mit solchen kaputten Makros missbraucht, wird bald ohne Freunde sein. Es ist allgemein bekannt, dass eine einfache Textersetzung von Dingen, die nicht streng durch Klammern geschützt sind, zu einem äußerst unauffälligen Bruch führen kann, weshalb C++ so viele Möglichkeiten einführt, Dinge zu tun ohne der C-Präprozessor, wie Vorlagen und static const bool TRUE = true;. (Obwohl diese Definition tatsächlich eine Art von hat intnicht bool.)

    – Peter Cordes

    30. Mai 2019 um 11:22 Uhr

Benutzeravatar von BlackDwarf
Schwarzer Zwerg

Es ist nur eine andere Art zu schreiben

#define TRUE 1
#define FALSE 0

Der Ausdruck "https://stackoverflow.com/"/"https://stackoverflow.com/" teilt den Zeichenwert von "https://stackoverflow.com/" von selbst, was als Ergebnis 1 ergibt.

Der Ausdruck '-'-'-' subtrahiert den char-Wert von '-' von sich selbst, was als Ergebnis 0 ergibt.

Klammern um das Ganze define Ausdrücke fehlen jedoch, 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 Umwandlungsoperator im C-Stil. Wenn sich jemand entscheidet, diese Ausdrücke zu übertragen bool in C++ zum Beispiel:

#include <iostream>

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

int main() {
    std::cout << "True: " << (bool) TRUE << std::endl;
    std::cout << "False: " << (bool) FALSE << std::endl;
    return 0;
}

Hier ist, was wir bekommen:

True: 0
False: -44

So (bool) TRUE würde eigentlich zu bewerten falseund (bool) FALSE würde zu bewerten true.

Benutzeravatar von Sufian Latif
Sufian Latif

Es ist gleichbedeutend mit dem Schreiben

#define TRUE 1
#define FALSE 0

Was für ein Ausdruck "https://stackoverflow.com/"/"https://stackoverflow.com/" tatsächlich teilt den Charakter / (was auch immer sein numerischer Wert ist) von selbst, also wird es 1.

Ebenso der Ausdruck '-'-'-' subtrahiert das Zeichen - von sich selbst und wertet zu 0.

Schreiben wäre besser

#define TRUE ("https://stackoverflow.com/"/"https://stackoverflow.com/")
#define FALSE ('-'-'-')

um eine versehentliche Änderung von Werten zu vermeiden, wenn sie mit anderen Operatoren mit höherer Priorität verwendet werden.

Benutzeravatar von ouah
ouah

Jay hat bereits beantwortet, warum die Werte dieser Ausdrücke sind 0 und 1.

Um der Geschichte willen, diese Ausdrücke "https://stackoverflow.com/"/"https://stackoverflow.com/" und '-'-'-' stammen aus einem der Einträge von 1. Internationaler Wettbewerb für verschleierten C-Code im Jahr 1984:

int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n","https://stackoverflow.com/"/"https://stackoverflow.com/"));}read(j,i,p){write(j/p+p,i---j,i/i);}

(Link zum Programm hiergibt es auf der IOCCC-Seite oben einen Hinweis darauf, was dieses Programm tut.)

Auch wenn ich mich richtig erinnere diese Ausdrücke als verschleierte Makros für TRUE und FALSE wurden auch im Buch „Obfuscated C and Other Mysteries“ von Don Libes (1993) behandelt.

Benutzeravatar von anand
und

Es ist eine urkomische Art, Makros für zu schreiben True und False.

So viele Erklärungen wurden geliefert / bedeutet eine 1-Byte-Zahl (gemäß ASCII), wenn sie durch sich selbst geteilt wird 1 was behandelt wird als True und ebenfalls - ist wieder eine Bytenummer, wenn derselbe Wert subtrahiert wird, den Sie erhalten 0 was interpretiert wird als false

#define TRUE  "https://stackoverflow.com/"/"https://stackoverflow.com/"
#define FALSE '-'-'-'

daher können wir ersetzen / oder - mit jedem beliebigen Zeichen, zum Beispiel:

#define TRUE  '!"https://stackoverflow.com/"!'
#define FALSE 'o'-'o'

Behält dieselbe Bedeutung wie der ursprüngliche Ausdruck bei.

Fabiens Benutzeravatar
Fabien

Beginnen wir mit wahr. Sie können es lesen als "https://stackoverflow.com/" / "https://stackoverflow.com/", was “Zeichen “https://stackoverflow.com/” geteilt durch Zeichen “https://stackoverflow.com/”” bedeutet. Da jedes Zeichen in C ein numerischer Wert (auf einem Byte) ist, kann es gelesen werden als „der ASCII-Wert des Zeichens „https://stackoverflow.com/“ dividiert durch den ASCII-Wert desselben Zeichens“, was bedeutet 1 (weil x/x offensichtlich 1 ist). Somit, TRUE ist 1.

Zum FALSEes ist die gleiche Begründung: '-'-'-' liest '-' - '-'dh “der ASCII-Wert von ‘-‘ minus dem ASCII-Wert von ‘-‘”, was 0 ist. Daher ist FALSE ist 0.

Das ist eine hässliche Art, das Offensichtliche auszudrücken.

1426970cookie-checkSeltsame Definitionen von TRUE- und FALSE-Makros

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy