Dziwne definicje makr TRUE I FALSE

Widziałem następujące definicje makr w książce kodowania.

#define TRUE  '/'/'/'
#define FALSE '-'-'-'
Nie było tam żadnego wyjaśnienia.

Proszę mi wyjaśnić, jak będą one działać jako TRUE i FALSE.

Author: Keshava GN, 2015-12-03

6 answers

Spójrzmy: '/' / '/' oznacza char literal /, podzielony przez char literal '/'. Wynik jest taki, który brzmi rozsądnie dla TRUE.

I '-' - '-' oznacza char literal '-', odejmowany od siebie. To jest zero (FALSE).

Są z tym dwa problemy: po pierwsze, nie jest to czytelne. Używanie 1 i 0 jest absolutnie lepsze. Ponadto, jak zauważyli TartanLlama i KerrekSB, jeśli kiedykolwiek będziesz używał tej definicji, proszę dodaj nawiasy wokół nich więc nie będziesz miał żadnych niespodzianek:

#include <stdio.h>

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

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

To wyświetli wartość char literal '-' (45 W moim systemie).

W nawiasie:

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

Program poprawnie wypisuje zero, chociaż nie ma sensu mnożyć wartości prawdy przez liczbę całkowitą, ale jest to tylko przykład nieoczekiwanych błędów, które mogą cię ugryźć, jeśli nie umieścisz swoich makr w nawiasach.

 372
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-03 10:11:51

To po prostu inny sposób pisania

#define TRUE 1
#define FALSE 0

Wyrażenie '/'/'/' podzieli wartość znaku '/' przez siebie, co da 1 w wyniku.

Wyrażenie '-'-'-' odejmuje od siebie wartość znaku '-', co w rezultacie daje 0.

Brakuje nawiasów wokół całych wyrażeń define, co może prowadzić do błędów w kodzie przy użyciu tych makr. odpowiedź Jaya bardzo dobrze to ujmuje.

Przykład "prawdziwym" scenariuszem, w którym zapominanie nawiasów może być szkodliwe, jest połączone użycie tych makr z operatorem c-style cast. Jeśli ktoś zdecyduje się wrzucić te wyrażenia do bool W C++ na przykład:

#include <iostream>

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

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

Oto co otrzymujemy:

True: 0
False: -44

Więc (bool) TRUE faktycznie oceniłby do false, a (bool) FALSE oceniłby do true.

 84
Author: BlackDwarf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:19

Jest odpowiednikiem zapisu

#define TRUE 1
#define FALSE 0

To, co w rzeczywistości robi wyrażenie '/'/'/', to dzielenie znaku / (niezależnie od jego wartości liczbowej) samo w sobie, więc staje się 1.

Podobnie, wyrażenie '-'-'-' odejmuje znak - od siebie i ewaluuje do 0.

Lepiej by było napisać

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

Aby uniknąć przypadkowej zmiany wartości w przypadku użycia z innymi operatorami o wyższym priorytecie.

 44
Author: 0605002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-30 01:22:41

Jay już odpowiedział, Dlaczego wartości tych wyrażeń to 0 i 1.

Ze względu na historię, te wyrażenia '/'/'/' i '-'-'-' pochodzą z jednego z zgłoszeń I Międzynarodowego Konkursu o ukryty kod C w 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 do programu tutaj , jest podpowiedź co ten program robi na stronie IOCCC powyżej.)

Również jeśli dobrze pamiętam te wyrażenia jako zaciemnione makra dla TRUE i FALSE były również w 1993 roku ukazała się książka Dona Libesa"Obfuscated C and Other Mysteries"("zaciemnione C i inne tajemnice").

 31
Author: ouah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:10

Zacznijmy od prawdy. Można go odczytać jako '/' / '/', co oznacza "znak' / 'podzielony przez znak'/'". Ponieważ każdy znak w C jest wartością liczbową (na jednym bajcie), można go odczytać jako "wartość ASCII znaku '/' podzielona przez wartość ASCII tego samego znaku", co oznacza 1 (ponieważ, oczywiście, X/X jest 1). Stąd TRUE jest 1.

Dla FALSE, to samo rozumowanie: '-'-'-' czyta '-' - '-', czyli "wartość ASCII' - 'minus wartość ASCII' -'", która wynosi 0. Stąd FALSE jest 0.

To paskudny sposób na stwierdzenie oczywistości.
 6
Author: Fabien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-03 09:50:50

To świetny sposób na pisanie makr dla True i False.

Jak wiele wyjaśnień zostało dostarczonych / oznacza liczbę bajtową(zgodnie z ASCII) po podzieleniu przez siebie daje 1, która będzie traktowana jako True i podobnie - jest ponownie liczbą bajtową po odjęciu tej samej wartości daje 0, która będzie interpretowana jako false {13]}

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

Stąd możemy zastąpić / lub - dowolnym znakiem, na przykład:

#define TRUE  '!'/'!'
#define FALSE 'o'-'o'

Zachowa to samo znaczenie co oryginalne wyrażenie.

 6
Author: anand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-22 08:48:19