To pytanie może wydawać się głupie, ale dlaczego 0
ewaluuje false
i jakąkolwiek inną wartość [całkowitą] true
to większość języków programowania?
Porównanie ciągów
Ponieważ pytanie wydaje się nieco zbyt proste, wyjaśnię się trochę bardziej: po pierwsze, może się wydawać oczywiste dla każdego programisty, ale dlaczego nie byłoby języka programowania - może być, ale nie może Użyłem - gdzie 0
ewaluuje true
i wszystkie inne wartości [całkowite] false
? Ta jedna uwaga może wydawać się przypadkowa, ale mam kilka przykładów, w których może to być dobry pomysł. Po pierwsze, weźmy przykład trójstronnego porównania ciągów, wezmę C strcmp
jako przykład: każdy programista próbujący C jako swojego pierwszego języka może ulec pokusie napisania następującego kodu:
if (strcmp(str1, str2)) { // Do something... }
Ponieważ strcmp
zwroty, 0
które oceniają, false
kiedy łańcuchy są równe, to, co początkowy programista próbował zrobić, kończy się niepowodzeniem i na ogół nie rozumie dlaczego na początku. Oceniając, 0
że true
zamiast tego, funkcja ta mogłaby zostać użyta w jej najprostszym wyrażeniu - powyższym - przy porównywaniu pod kątem równości, a odpowiednie kontrole dla -1
i 1
zostałyby wykonane tylko w razie potrzeby. Przez większość czasu uważalibyśmy ten typ zwrotu za bool
(naszym zdaniem ).
Ponadto, niech wprowadzi nowy typ, sign
, że po prostu ma wartości -1
, 0
a 1
. To może być całkiem przydatne. Wyobraź sobie, że w C ++ jest operator statku kosmicznego i my go potrzebujemy std::string
(cóż, jest już compare
funkcja, ale operator statku kosmicznego jest bardziej zabawny). Deklaracja będzie obecnie następująca:
sign operator<=>(const std::string& lhs, const std::string& rhs);
Gdybyśmy 0
zostali oceniani true
, operator statku kosmicznego nawet by nie istniał i moglibyśmy w operator==
ten sposób zadeklarować :
sign operator==(const std::string& lhs, const std::string& rhs);
To operator==
poradziłoby sobie z porównywaniem w trzech kierunkach jednocześnie i nadal mogłoby być użyte do wykonania następującego sprawdzenia, a jednocześnie byłoby w stanie sprawdzić, który ciąg znaków jest lepszy leksykograficznie od drugiego w razie potrzeby:
if (str1 == str2) { // Do something... }
Stara obsługa błędów
Mamy teraz wyjątki, więc ta część dotyczy tylko starych języków, w których nic takiego nie istnieje (na przykład C). Jeśli spojrzymy na standardową bibliotekę C (a także POSIX), możemy zobaczyć na pewno, że funkcje maaaaany powrócą 0
po pomyślnym zakończeniu, a dowolna liczba całkowita w przeciwnym razie. Niestety niektórzy ludzie robią takie rzeczy:
#define TRUE 0
// ...
if (some_function() == TRUE)
{
// Here, TRUE would mean success...
// Do something
}
Jeśli myślimy o tym, jak myślimy w programowaniu, często mamy następujący wzór rozumowania:
Do something
Did it work?
Yes ->
That's ok, one case to handle
No ->
Why? Many cases to handle
Jeśli pomyślimy o tym jeszcze raz, sensowne byłoby umieszczenie jedynej wartości neutralnej 0
, do yes
(i tak działają funkcje C), podczas gdy wszystkie inne wartości mogą tam być, aby rozwiązać wiele przypadków no
. Jednak we wszystkich językach programowania, które znam (oprócz być może niektórych eksperymentalnych języków ezoterycznych), które yes
oceniają false
pod if
warunkiem, podczas gdy wszystkie no
przypadki oceniają true
. Istnieje wiele sytuacji, w których „to działa” reprezentuje jeden przypadek, podczas gdy „to nie działa” reprezentuje wiele prawdopodobnych przyczyn. Jeśli pomyślimy o tym w ten sposób, dokonanie 0
oceny true
i reszty do false
byłoby znacznie bardziej sensowne.
Wniosek
Mój wniosek jest zasadniczo moim pierwotnym pytaniem: dlaczego zaprojektowaliśmy języki, gdzie 0
są false
i inne wartości true
, biorąc pod uwagę moje kilka przykładów powyżej, a może kilka innych, o których nie myślałem?
Dalsze działania: Miło jest widzieć, że istnieje wiele odpowiedzi z wieloma pomysłami i tak wiele możliwych powodów, aby tak było. Uwielbiam, jak bardzo pasjonujesz się tym. Oryginalnie zadałem to pytanie z nudów, ale ponieważ wydajesz się tak namiętny, postanowiłem pójść nieco dalej i zapytać o uzasadnienie logicznego wyboru dla 0 i 1 na Math.SE :)
źródło
strcmp()
nie jest dobrym przykładem wartości prawda lub fałsz, ponieważ zwraca 3 różne wartości. Będziesz zaskoczony, gdy zaczniesz używać powłoki, gdzie 0 oznacza prawda, a wszystko inne oznacza fałsz.if true ; then ... ; fi
, gdzietrue
jest poleceniem, które zwraca zero, a to każeif
uruchomić...
.bool
typu, ale porównań / jeśli warunki itd. Może mieć dowolną wartość.Odpowiedzi:
0
tofalse
dlatego, że oba są zerowymi elementami we wspólnych semirings . Mimo że są to odrębne typy danych, intuicyjny sens ma konwersja między nimi, ponieważ należą one do izomorficznych struktur algebraicznych.0
to tożsamość dodawania i zero dla mnożenia. Dotyczy to liczb całkowitych i wymiernych, ale nie liczb zmiennoprzecinkowych IEEE-754:0.0 * NaN = NaN
i0.0 * Infinity = NaN
.false
to tożsamość logiczna xor (⊻) i zero dla logicznej i (∧). Jeśli booleany są reprezentowane jako {0, 1} - zbiór liczb całkowitych modulo 2 - możesz myśleć o ⊻ jako dodatku bez przenoszenia i ∧ jako pomnożeniu.""
i[]
są tożsamością do konkatenacji, ale istnieje kilka operacji, dla których mają sens jako zero. Powtarzanie jest jedno, ale powtarzanie i konkatenacja nie rozdzielają, więc te operacje nie tworzą semiery.Takie niejawne konwersje są pomocne w małych programach, ale w dużych mogą utrudniać programowanie. To tylko jeden z wielu kompromisów w projektowaniu języka.
źródło
nil
czy zarówno pusta lista, jak[]
ifalse
wartość w Common Lisp; czy istnieje tendencja do łączenia tożsamości z różnych typów danych?) Nadal musisz wyjaśnić, dlaczego naturalne jest uznawanie fałszu za tożsamość addytywną i prawdziwego za tożsamość multiplikatywną i nie na odwrót. Czy nie można uznaćtrue
za identyfikatorAND
i zero dlaOR
?true
to także tożsamość i zero semirings (boolean i / lub). Nie ma powodu, dla którego konwencja Appart jest do rozważeniafalse
bliższa 0 niżtrue
.Ponieważ matematyka działa.
Tradycyjnie programy C mają takie warunki
zamiast
ponieważ pojęcie zerowego równoważnika fałszu jest dobrze zrozumiane.
źródło
Jak powiedzieli inni, matematyka była najważniejsza. Dlatego 0 to
false
i 1 totrue
.O której matematyce mówimy? Algebry boolowskie, które pochodzą z połowy XIX wieku, na długo przed pojawieniem się komputerów cyfrowych.
Można również powiedzieć, że konwencja wyszła z logiki zdań , która jest nawet starsza niż algebry boolowskie. Jest to sformalizowanie wielu logicznych wyników, które programiści znają i kochają (
false || x
równa sięx
,true && x
równa sięx
itd.).Zasadniczo mówimy o arytmetyki na zbiorze z dwoma elementami. Pomyśl o liczeniu binarnym. Algebry boolowskie są źródłem tej koncepcji i jej teoretycznych podstaw. Konwencje języków takich jak C to tylko prosta aplikacja.
źródło
true = 1
. To nie jest całkiem dokładne, ponieważtrue != 0
to nie jest dokładnie to samo. Jednym z powodów (nie jedynym), dlaczego należy unikać takich porównańif(something == true) { ... }
.Myślałem, że ma to związek z „dziedziczeniem” po elektronice, a także algebrą boolowską, gdzie
0
=off
,negative
,no
,false
1
=on
,positive
,yes
,true
strcmp zwraca 0, gdy łańcuchy są równe, ma związek z jego implementacją, ponieważ tak naprawdę robi to, aby obliczyć „odległość” między dwoma łańcuchami. To, że 0 również jest uważane za fałszywe, jest tylko zbiegiem okoliczności.
zwracanie 0 po sukcesie ma sens, ponieważ 0 w tym przypadku oznacza brak błędu i każda inna liczba byłaby kodem błędu. Użycie dowolnego innego numeru do sukcesu nie miałoby większego sensu, ponieważ masz tylko jeden kod sukcesu, a możesz mieć kilka kodów błędów. Używasz „Czy to zadziałało?” jako wyrażenie instrukcji if i powiedzenie 0 = yes miałoby większy sens, ale wyrażenie jest bardziej poprawne „Czy coś poszło nie tak?” i wtedy widać, że 0 = nie ma większego sensu. Myślenie o
false/true
tym naprawdę nie ma sensu, bo tak naprawdę jestno error code/error code
.źródło
0
zasuccess/no error
to jedyną rzeczą, która ma sens, kiedy inne całkowite reprezentują kody błędów. To0
również zdarza się reprezentowaćfalse
w innych przypadkach, nie ma to tak naprawdę znaczenia, ponieważ nie mówimy tutaj wcale o prawdzie lub fałszu;)strcmp()
obliczania odległości jest całkiem dobry. Gdyby to zostało nazwanestrdiff()
następnieif (!strdiff())
byłoby bardzo logiczne.Jak wyjaśniono w tym artykule , wartości
false
itrue
nie należy ich mylić z liczbami całkowitymi 0 i 1, ale można je utożsamiać z elementami pola Galois (pole skończone) dwóch elementów (patrz tutaj ).Pole to zbiór dwóch operacji, które spełniają określone aksjomaty.
Symbole 0 i 1 są konwencjonalnie używane do oznaczenia addytywnej i multiplikatywnej tożsamości pola, ponieważ liczby rzeczywiste są również polem (ale nie skończonym), którego tożsamości to liczby 0 i 1.
Tożsamość addytywna to element 0 pola, taki że dla wszystkich x:
a tożsamość multiplikatywna to element 1 pola, taki że dla wszystkich x:
Pole skończone dwóch elementów ma tylko te dwa elementy, mianowicie addytywną tożsamość 0 (lub
false
) i multiplikatywną tożsamość 1 (lubtrue
). Dwie operacje tego pola to logiczny XOR (+) i logiczny AND (*).Uwaga. Jeśli odwrócisz operacje (XOR to mnożenie, a AND to dodawanie), to mnożenie nie rozdziela po dodaniu i nie masz już pola. W takim przypadku nie ma powodu, aby wywoływać dwa elementy 0 i 1 (w dowolnej kolejności). Zauważ też, że nie możesz wybrać operacji OR zamiast XOR: bez względu na to, jak interpretujesz OR / AND jako dodawanie / mnożenie, wynikowa struktura nie jest polem (nie wszystkie elementy odwrotne istnieją zgodnie z wymaganiami aksjomatów pola).
Odnośnie funkcji C:
strcmp
oblicza różnicę między dwoma łańcuchami. 0 oznacza, że nie ma różnicy między dwoma ciągami, tzn. Że dwa ciągi są równe.Powyższe intuicyjne wyjaśnienia mogą pomóc zapamiętać interpretację zwracanych wartości, ale jeszcze łatwiej jest po prostu sprawdzić dokumentację biblioteki.
źródło
Należy wziąć pod uwagę, że alternatywne systemy mogą być również akceptowalnymi decyzjami projektowymi.
Powłoki: 0 stan wyjścia jest prawdą, niezerowe to fałsz
Podano już przykład powłok traktujących status wyjścia 0 jako prawdziwy.
Uzasadnieniem jest to, że istnieje jeden sposób na sukces, ale wiele sposobów na porażkę, więc użycie 0 jako specjalnej wartości oznaczającej „brak błędów” jest pragmatyczne.
Ruby: 0 jest jak każda inna liczba
Wśród „normalnych” języków programowania istnieją pewne wartości odstające, takie jak Ruby, które traktują 0 jako prawdziwą wartość.
Uzasadnieniem jest to, że tylko
false
inil
powinny być fałszywe. Dla wielu nowicjuszy Ruby jest to problem. Jednak w niektórych przypadkach dobrze, że 0 jest traktowane jak każda inna liczba.Jednak taki system działa tylko w języku, który jest w stanie odróżnić booleany jako osobny typ od liczb. We wcześniejszych czasach komputerów programiści pracujący z językiem asemblera lub surowym językiem maszynowym nie mieli takich luksusów. Prawdopodobnie naturalne jest traktowanie 0 jako stanu „pustego” i ustawianie wartości 1 na flagę, gdy kod wykryje, że coś się wydarzyło. W konsekwencji konwencja opracowała, że zero traktowano jako fałsz, a wartości niezerowe zaczęto traktować jako prawdziwe. Jednak nie musi tak być.
Java: Liczby w ogóle nie mogą być traktowane jako logiczne
W języku Java,
true
afalse
są tylko wartości logiczne. Liczby nie są liczbami logicznymi i nie można ich nawet przeliczyć na wartości logiczne ( Java Language Specification, Sec 4.2.2 ):Ta reguła po prostu całkowicie eliminuje pytanie - wszystkie wyrażenia logiczne muszą być wyraźnie zapisane w kodzie.
źródło
if (thing === 0)
, to po prostu nie jest fajne.0
jesttrue
(jak każdy inny Integer) w dynamicznym języku. Czasami zdarzyło mi się złapać,0
gdy próbuję złapaćNone
w Pythonie, a czasem może to być dość trudne do wykrycia.if [ 0 ] ; then echo this executes ; fi
. Fałszywa wartość danych jest pusty ciąg znaków, a sprawdzalne fałsz to udało stan wypowiedzenie komendy, która jest reprezentowana przez nie -ZERO.Przed zajęciem się ogólną sprawą możemy omówić twoje przykłady dotyczące przeciwników.
Porównanie ciągów
To samo dotyczy wielu rodzajów porównań. Takie porównania obliczają odległość między dwoma obiektami. Gdy obiekty są równe, odległość jest minimalna. Kiedy więc „porównanie się powiedzie”, wartość wynosi 0. Ale tak naprawdę wartość zwracana nie
strcmp
jest wartością logiczną, jest to odległość i to, co pułapkuje nieświadomych programistów .if (strcmp(...)) do_when_equal() else do_when_not_equal()
W C ++ możemy przeprojektować,
strcmp
aby zwrócićDistance
obiekt, który zastępujeoperator bool()
zwracanie true, gdy 0 (ale wtedy ugryzłby cię inny zestaw problemów). Lub w zwykłym C mają po prostustreq
funkcję, która zwraca 1, gdy łańcuchy są równe, a 0 w przeciwnym razie.Wywołania API / kod wyjścia programu
Tutaj zależy Ci na tym, dlaczego coś poszło nie tak, ponieważ spowoduje to błędne decyzje. Kiedy wszystko się powiedzie, nie chcesz wiedzieć nic konkretnego - twoje zamiary są realizowane. Zwracana wartość musi zatem przekazywać te informacje. To nie jest wartość logiczna, to kod błędu. Specjalna wartość błędu 0 oznacza „brak błędu”. Reszta zakresu reprezentuje lokalnie znaczące błędy, z którymi musisz sobie poradzić (w tym 1, co często oznacza „nieokreślony błąd”).
Ogólna sprawa
To pozostawia nas z pytaniem: dlaczego są wartości logiczne
True
iFalse
powszechnie reprezentowane z 1 i 0, odpowiednio?Poza subiektywnym argumentem „tak jest lepiej”, oto kilka powodów (również subiektywnych), o których mogę myśleć:
analogia obwodu elektrycznego. Prąd jest WŁĄCZONY przez 1 s, a WYŁĄCZONY przez 0 s. Lubię mieć (1, Tak, Prawda, Wł.) Razem i (0, Nie, Fałsz, Wył.) Zamiast innej mieszanki
inicjalizacje pamięci. Kiedy jestem
memset(0)
zbiorem zmiennych (niezależnie od tego, czy są to liczby całkowite, zmiennoprzecinkowe, boolowe), chcę, aby ich wartość odpowiadała najbardziej konserwatywnym założeniom. Np. Moja suma wynosi początkowo 0, predykat to Fałsz itp.Być może wszystkie te powody są związane z moją edukacją - gdybym nauczył mnie kojarzyć 0 z True od samego początku, poszedłbym na odwrót.
źródło
bool
.int
celubool
w wielu językach programowania. Porównywanie i wykonywanie gestów błędów to tylko przykłady miejsc, w których rzutowanie go w inny sposób niż ten, który obecnie wykonuje, miałoby sens.Z wysokiego poziomu mówisz o trzech zupełnie różnych typach danych:
Wartość logiczna. Konwencja matematyczna w algebrze boolowskiej polega na użyciu 0 dla
false
i 1 dlatrue
, więc warto stosować się do tej konwencji. Myślę, że ten sposób ma również bardziej intuicyjny sens.Wynik porównania. To ma trzy wartości:
<
,=
i>
(Zauważ, że żaden z nich nie jesttrue
). Dla nich sensowne jest użycie odpowiednio wartości -1, 0 i 1 (lub, bardziej ogólnie, wartości ujemnej, zero i wartości dodatniej).Jeśli chcesz sprawdzić równość i masz tylko funkcję, która wykonuje ogólne porównanie, myślę, że powinieneś to wyraźnie określić za pomocą czegoś podobnego
strcmp(str1, str2) == 0
. Używanie!
w tej sytuacji jest mylące, ponieważ traktuje wartość niebędącą wartością logiczną tak, jakby była wartością logiczną.Pamiętaj też, że porównanie i równość nie muszą być tym samym. Na przykład, jeśli zamówisz ludzi według daty urodzenia,
Compare(me, myTwin)
powinien powrócić0
, aleEquals(me, myTwin)
powinien powrócićfalse
.Sukces lub niepowodzenie funkcji, być może również ze szczegółami na temat tego sukcesu lub niepowodzenia. Jeśli mówisz o systemie Windows, ten typ jest wywoływany,
HRESULT
a niezerowa wartość niekoniecznie oznacza awarię. W rzeczywistości wartość ujemna oznacza niepowodzenie i nieujemny sukces. Wartość sukcesu jest bardzo częstoS_OK = 0
, ale może to być na przykładS_FALSE = 1
inne wartości.Zamieszanie wynika z faktu, że trzy logicznie całkiem różne typy danych są w rzeczywistości reprezentowane jako pojedynczy typ danych (liczba całkowita) w C i niektórych innych językach oraz że można użyć liczby całkowitej w jednym warunku. Ale nie sądzę, aby sensowne było redefiniowanie wartości logicznej, aby uprościć korzystanie z niektórych typów nie-logicznych.
Weź również pod uwagę inny typ, który jest często używany w warunku w C: wskaźnik. Tam naturalne jest traktowanie jako
NULL
-pointer (który jest reprezentowany jako0
) jakofalse
. Zatem zastosowanie się do Twojej sugestii utrudniłoby również pracę ze wskaźnikami. (Chociaż osobiście wolę jawnie porównywać wskaźnikiNULL
, niż traktować je jako logiczne).źródło
Zero może być fałszywe, ponieważ większość procesorów ma flagę ZERO, której można użyć do rozgałęzienia. Zapisuje operację porównania.
Zobaczmy dlaczego.
Niektóre psuedocode, ponieważ publiczność prawdopodobnie nie czyta asemblera
c- źródło prostych wywołań pętli wibble 10 razy
trochę udawać, że to zgromadziło
c- źródło kolejnej prostej wywołania pętli wibble 10 razy
trochę udawaj, że to sprawa
trochę więcej c źródła
i zgromadzenie
widzisz jak to jest krótkie?
trochę więcej c źródła
i zespół (załóżmy, że marginalnie inteligentny kompilator może zastąpić == 0 bez porównania)
Teraz wypróbujmy konwencję true = 1
trochę więcej c źródło # zdefiniować PRAWDA 1 int foo = PRAWDA; if (foo == TRUE) wibble ()
i zgromadzenie
widzisz, jak krótki jest przypadek z niezerową wartością true?
Naprawdę wczesne procesory miały małe zestawy flag przymocowane do akumulatora.
Aby sprawdzić, czy a> b lub a = b ogólnie wymaga instrukcji porównania.
Przeanalizujmy to. Na niektórych starszych procesorach nie trzeba było używać instrukcji porównywania dla akumulatora równego ZERO lub akumulatora mniejszego niż zero.
Czy rozumiesz teraz, dlaczego zero może być fałszywe?
Uwaga: jest to kod psuedo i żaden zestaw instrukcji nie wygląda tak. Jeśli znasz się na montażu, wiesz, że tutaj dużo upraszczam. Jeśli wiesz coś o projektowaniu kompilatora, nie musiałeś czytać tej odpowiedzi. Każdy, kto wie coś na temat rozwijania pętli lub przewidywania gałęzi, klasa zaawansowana jest w korytarzu w pokoju 203.
źródło
if (foo)
iif (foo != 0)
powinien generować ten sam kod, a po drugie, jesteś pokazując, że język asemblera używasz w rzeczywistości ma jednoznacznych argumentów logicznych i testów dla nich. Na przykładjz
oznaczajump if zero
. Innymi słowyif (a == 0) goto target;
. A ilość nie jest nawet testowana bezpośrednio; warunek jest konwertowany na jego flagę logiczną, która jest przechowywana w specjalnym słowie maszynowym. Właściwie to bardziejcpu.flags.zero = (a == 0); if (cpu.flags.zero) goto target;
jz
instrukcję, ale niejnz
? (lub jakikolwiek inny asymetryczny zestaw instrukcji warunkowych)Istnieje wiele odpowiedzi, które sugerują, że pewna właściwość matematyczna wymaga zgodności między 1 a prawdą. Nie mogę znaleźć żadnej takiej nieruchomości i sugeruję, że jest to konwencja czysto historyczna.
Biorąc pod uwagę pole z dwoma elementami, mamy dwie operacje: dodawanie i mnożenie. Możemy zmapować operacje logiczne na tym polu na dwa sposoby:
Tradycyjnie identyfikujemy Prawda z 1, a Fałsz z 0. Identyfikujemy ORAZ *, a XOR z +. Zatem OR jest nasycającym dodatkiem.
Jednak równie łatwo moglibyśmy zidentyfikować Prawda z 0, a Fałsz z 1. Następnie identyfikujemy OR z * i XNOR z +. Zatem AND jest nasycającym dodatkiem.
źródło
O dziwo zero nie zawsze jest fałszywe.
W szczególności konwencja Unix i Posix ma być zdefiniowana
EXIT_SUCCESS
jako 0 (iEXIT_FAILURE
jako 1). W rzeczywistości jest to nawet standardowa konwencja C. !Tak dla pocisków Posix i exit (2) wywołań systemowych 0 oznacza „sukces”, co intuicyjnie jest bardziej prawdziwe niż fałszywe.
W szczególności powłoka
if
chce powrotu procesuEXIT_SUCCESS
(czyli 0), aby podążał za swoją gałęzią „wtedy”!Na schemacie (ale nie we wspólnym Lisp lub MELT ) 0 i zero (tj. Na
()
schemacie) są prawdziwe, ponieważ jedyną fałszywą wartością jest#f
Zgadzam się, robię dupki!
źródło
C jest używany do programowania niskopoziomowego blisko sprzętu, obszaru, w którym czasami trzeba przechodzić między operacjami bitowymi i logicznymi na tych samych danych. Konieczność konwersji wyrażenia liczbowego na wartość boolowską tylko w celu wykonania testu zaśmieciłaby kod.
Możesz pisać takie rzeczy jak:
zamiast
W jednym odosobnionym przykładzie nie jest tak źle, ale zrobienie tego stanie się irytujące.
Podobnie, operacje konwersacyjne. Przydaje się w wyniku operacji boolowskiej, takiej jak porównanie, wygenerowanie 0 lub 1: Załóżmy, że chcemy ustawić trzeci bit jakiegoś słowa na podstawie tego, czy
modemctrl
bit wykrywa nośną:Tutaj musimy mieć
!= 0
, aby zredukować wynik&
wyrażenia biwise do0
lub1
, ale ponieważ wynik jest tylko liczbą całkowitą, nie musimy dodawać denerwujących rzutów, aby dalej konwertować wartość logiczną na liczbę całkowitą.Mimo że współczesne C ma teraz
bool
typ, nadal zachowuje ważność takiego kodu, zarówno dlatego, że jest to dobra rzecz, jak i z powodu ogromnego zerwania z kompatybilnością wsteczną, która byłaby spowodowana inaczej.Kolejny przykład, w którym C jest zręczny: testowanie dwóch warunków boolowskich jako przełącznika czterokierunkowego:
Nie można tego zabrać programatorowi C bez walki!
Wreszcie C czasami służy jako rodzaj języka asemblera na wysokim poziomie. W językach asemblera nie mamy również typów boolowskich. Wartość logiczna to tylko odrobina lub zero w stosunku do niezerowej wartości w lokalizacji pamięci lub rejestrze. Liczba całkowita zero, zero logiczne i adres zero są testowane w ten sam sposób w zestawach instrukcji języka asemblera (a być może nawet zmiennoprzecinkowe zero). Podobieństwo między C a językiem asemblera jest przydatne, na przykład, gdy C jest używany jako język docelowy do kompilacji innego języka (nawet takiego, który ma mocno wpisane wartości logiczne!)
źródło
Wartość logiczna lub prawda ma tylko 2 wartości. Prawda i fałsz.
Te nie powinny być przedstawione w postaci liczb całkowitych, ale jako bity (0 do 1).
Mówienie, że jakakolwiek inna liczba całkowita oprócz 0 lub 1 nie jest fałszem, jest mylącym stwierdzeniem. Tabele prawdy dotyczą wartości prawdy, a nie liczb całkowitych.
Z perspektywy wartości prawdy -1 lub 2 złamałoby wszystkie tabele prawdy i związaną z nimi logikę boolowską.
Większość języków ma zazwyczaj
boolean
typ, który po rzutowaniu na typ liczbowy, taki jak liczba całkowita, ujawnia wartość false do rzutowania jako liczba całkowita 0.źródło
TRUE
lubFALSE
. Nigdy nie powiedziałem - może tak zrobiłem, ale nie było to zamierzone - liczby całkowite były prawdziwe lub fałszywe, zapytałem o to, dlaczego oceniają je w zależności od tego, które wartości mają wartość boolowską.Ostatecznie mówisz o złamaniu podstawowego języka, ponieważ niektóre interfejsy API są kiepskie. Crappy APIs nie są nowe i nie można ich naprawić, łamiąc język. Jest matematycznym faktem, że 0 jest fałszem, a 1 jest prawdą, a każdy język, który tego nie szanuje, jest zasadniczo uszkodzony. Trójstronne porównanie jest niszowe i nie ma żadnego interesu, ponieważ jego wynik niejawnie przekształca się w
bool
ponieważ zwraca trzy możliwe wyniki. Stare interfejsy API C po prostu mają straszliwą obsługę błędów, a także są hamowane, ponieważ C nie ma niezbędnych funkcji językowych, aby nie mieć strasznych interfejsów.Zauważ, że nie mówię tego w przypadku języków, które nie mają niejawnej konwersji liczb całkowitych-> boolowskich.
źródło
+
symbol oznacza LUB. Na przykładabc + a'b'c
oznacza(a and b and c) or (a and (not b) and (not c))
.