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
.
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.
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
.
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.
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").
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.
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.
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