it-swarm.com.de

Seltsame Definitionen von TRUE- und FALSE-Makros

Ich habe die folgenden Makrodefinitionen in einem Codierungsbuch gesehen.

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

Es gab dort keine Erklärung.

Bitte erkläre mir, wie diese als TRUE und FALSE funktionieren.

297
Keshava GN

Mal sehen: '/' / '/' Bedeutet das char-Literal /, Geteilt durch das char-Literal '/' Selbst. Das Ergebnis ist eines, was für TRUE vernünftig klingt.

Und '-' - '-' Bedeutet das char Literal '-', Das von sich selbst abgezogen wird. Dies ist Null (FALSE).

Hierbei gibt es zwei Probleme: Erstens ist es nicht lesbar. Die Verwendung von 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;
}

Dies gibt den Wert des char -Literal '-' (45 auf meinem System) aus.

Mit Klammern:

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

das Programm gibt korrekt null aus, auch wenn es wenig sinnvoll ist, einen Wahrheitswert mit einer Ganzzahl zu multiplizieren. Es ist jedoch nur ein Beispiel für die Art unerwarteter Fehler, die Sie beißen können, wenn Sie Ihre Makros nicht in Klammern setzen.

377
Jay

Es ist nur eine andere Art zu schreiben

#define TRUE 1
#define FALSE 0

Der Ausdruck '/'/'/' dividiert den Zeichenwert von '/' für sich, was 1 ergibt.

Der Ausdruck '-'-'-' subtrahiert den Zeichenwert von '-' von sich selbst, was 0 ergibt.

Es fehlen jedoch eckige Klammern um die gesamten Ausdrücke define, 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-Cast-Operator. Wenn sich jemand entscheidet, diese Ausdrücke in C++ in bool umzuwandeln:

#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

Damit (bool) TRUE würde tatsächlich zu false und (bool) FALSE würde zu true ausgewertet.

88
BlackDwarf

Es ist gleichbedeutend mit Schreiben

#define TRUE 1
#define FALSE 0

Was der Ausdruck '/'/'/' teilt tatsächlich das Zeichen / (was auch immer sein numerischer Wert ist) für sich, so wird es 1.

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

Es wäre besser zu schreiben

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

um eine versehentliche Änderung der Werte bei Verwendung mit anderen Operatoren höherer Priorität zu vermeiden.

44
0605002

Jay hat bereits beantwortet, warum die Werte dieser Ausdrücke 0 Und 1 Sind.

Aus historischen Gründen stammen diese Ausdrücke '/'/'/' Und '-'-'-' Aus einem der Einträge von 1. 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 , auf der obigen IOCCC-Seite finden Sie einen Hinweis auf die Funktionsweise dieses Programms.)

Auch wenn ich mich richtig erinnere, wurden diese Ausdrücke als verschleierte Makros für TRUE und FALSE auch in "Verschleiertes C und andere Geheimnisse" Buch von Don Libes (1993) behandelt.

32
ouah

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

Da viele Erklärungen zur Verfügung gestellt wurden, bedeutet / eine 1-Byte-Zahl (gemäß ASCII), wenn sie durch sich selbst geteilt wird, und gibt Ihnen 1, die als True und ebenso behandelt wird - ist wieder eine Bytenummer, wenn derselbe Wert subtrahiert wird, den Sie erhalten. 0 wird als false interpretiert.

#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.

7
anand

Beginnen wir mit true. Sie können es als '/' / '/' Lesen, was "Zeichen '/' geteilt durch Zeichen '/'" bedeutet. Da jedes Zeichen in C ein numerischer Wert (in einem Byte) ist, kann er als "der ASCII Wert des Zeichens '/' geteilt durch den ASCII Wert dieses Zeichens" gelesen werden dasselbe Zeichen ", was 1 bedeutet (weil offensichtlich x/x 1 ist). Daher ist TRUE 1.

Für FALSE gilt das Gleiche: '-'-'-' Lautet '-' - '-', Dh "der ASCII-Wert von '-' abzüglich des ASCII Wert von '-' ", der 0 ist. Daher ist FALSE 0.

Dies ist eine üble Art, das Offensichtliche zu sagen.

6
Fabien