Czy możesz wyjaśnić, dlaczego są to najlepsze do najgorszych wyborów?
endolith
1
@endolith Wyrównanie, optymalizacje i sposób przechowywania <stdbool.h>boolwybranego kompilatora mogą być bardziej odpowiednie do zamierzonego celu wartości boolowskiej niż wykorzystanie int(tzn. kompilator może wybrać implementację boolinną niż an int). Jeśli masz szczęście, może to również skutkować bardziej rygorystycznym sprawdzaniem typu w czasie kompilacji.
blubberdiblub
1
Dlaczego warto korzystać intz bool? To marnotrawstwo. Zastosowanie unsigned char. Lub użyj polecenie wbudowane c za _Bool.
Bez Ciała
@NoBody Korzystanie z mniejszego typu może zaoszczędzić na pamięci, ale może nie przyspieszyć. Często szybsze jest użycie natywnego rozmiaru słowa procesora zamiast mniejszego, ponieważ może to wymagać od kompilatora zmiany bitów, aby poprawnie go wyrównać
Ted Klein Bergman
240
Kilka przemyśleń na temat booleanów w C:
Jestem wystarczająco stary, że używam zwykłego ints jako mojego typu logicznego bez żadnych typedefs, specjalnych definicji lub wyliczeń dla wartości prawda / fałsz. Jeśli zastosujesz się do mojej poniższej sugestii, aby nigdy nie porównywać stałych stałych boolowskich, wystarczy użyć 0/1, aby zainicjować flagi. Takie podejście można jednak uznać za zbyt reakcyjne w dzisiejszych czasach. W takim przypadku należy zdecydowanie skorzystać, <stdbool.h>ponieważ przynajmniej ma tę zaletę, że jest znormalizowana.
Jakiekolwiek są stałe logiczne, używaj ich tylko do inicjalizacji. Nigdy nie pisz czegoś takiego
if(ready == TRUE)...while(empty == FALSE)...
Zawsze można je zastąpić jaśniejszym
if(ready)...while(!empty)...
Pamiętaj, że można je właściwie odczytać na głos.
Nadaj swoim zmiennym logicznym pozytywne nazwy, tj full Zamiast notfull. Ten ostatni prowadzi do kodu, który jest trudny do odczytania. Porównać
if(full)...if(!full)...
z
if(!notfull)...if(notfull)...
Obie poprzednie pary czytają naturalnie, chociaż !notfulltrudno jest je czytać w obecnej postaci, i stają się znacznie gorsze w bardziej złożonych wyrażeniach boolowskich.
Ogólnie należy unikać argumentów logicznych. Rozważ funkcję zdefiniowaną w ten sposób
void foo(bool option){...}
W treści funkcji jest bardzo jasne, co oznacza argument, ponieważ ma wygodną i, miejmy nadzieję, znaczącą nazwę. Ale wyglądają strony z połączeniami
foo(TRUE);
foo(FALSE):
W tym przypadku zasadniczo nie można powiedzieć, co oznacza parametr, nie zawsze patrząc na definicję lub deklarację funkcji, a staje się znacznie gorzej, gdy dodasz jeszcze więcej parametrów boolowskich. Sugeruję albo
A jak porównać dwie zmienne dla równości? Nigdy nie używaj stałych boolowskich działa świetnie, ale nie rozwiązuje problemu w porównaniu z niestałymi.
Baruch
Wybacz mi, ale nie rozumiem pytania. Czy pytasz, jak porównać dwie zmienne boolowskie pod kątem równości? Jeśli tak, to nie a == bdziała?
Dale Hagglund
5
@ Kenji To, co mówisz, jest prawdą, chociaż uważam, że używanie wartości innych niż jedna jako równoważnika prawdy jest prawie zawsze złym pomysłem. Więc w twoim przykładzie, zakładając to ai blicząc od zera, poleciłbym a > 0 == b > 0zamiast tego. Jeśli nalegasz na wykorzystanie prawdziwości arbitralnych niezerowych wartości, otrzymasz !!varwartość logiczną 0/1 równą var, więc możesz napisać !!a == !!b, chociaż wielu czytelników uzna to za mylące.
Dale Hagglund
3
!a == !bjest również wystarczający do testowania równości, niezerowe stają się zerami, a zera stają się jednością.
ryanpattison
5
@rpattiso Masz rację, oczywiście, ale myślę, że przeczytałbym !!ajako „przekonwertować wartość niebędącą boolowską na jej równoważną wartość prawdy”, podczas gdy przeczytałbym !ajako „logicznie odwróć zmienną boolowską a”. W szczególności szukałem konkretnego powodu, dla którego logiczna inwersja była pożądana.
Dale Hagglund,
88
Wartość logiczna w C jest liczbą całkowitą: zero dla wartości false i niezerowa dla wartości true.
Działa dobrze również z operatorami logicznymi (&& i ||).
Vultrao
74
Oto wersja, której użyłem:
typedefenum{false=0,true=!false}bool;
Ponieważ fałsz ma tylko jedną wartość, ale logiczna prawda może mieć wiele wartości, ale technika ustawia true na to, co kompilator użyje w przeciwieństwie do fałszu.
To rozwiązuje problem z kodowaniem czegoś, co sprowadzałoby się do tego:
if(true==!false)
Myślę, że wszyscy zgodzilibyśmy się, że nie jest to dobra praktyka, ale jednorazowy koszt wykonania „prawda =! Fałsz” eliminujemy ten problem.
Pierwszy (najbardziej odpowiedni)! konwertuje niezerową liczbę całkowitą na 0, a następnie drugą (najbardziej w lewo)! konwertuje 0 na amyfalse wartość. Zostawię to jako ćwiczenie dla czytelnika do konwersji zerowej liczby całkowitej.
[EDYCJA] Moim stylem jest używanie jawnego ustawienia wartości w wyliczeniu, gdy wymagana jest konkretna wartość, nawet jeśli wartość domyślna byłaby taka sama. Przykład: Ponieważ fałsz musi wynosić zero, używam false = 0,raczej niżfalse,
Również Inną korzyścią wynikającą z korzystania teksty stałe jest integracja IDE - true, falsei boolsą podświetlone w większości IDE, ponieważ są wartości enum i typedef, w przeciwieństwie do #defines, które są rzadko składnia podświetlona.
Ciekawe: ignorując, czy to faktycznie działa, czy jest poprawne C (99+), aby umożliwić wyliczeniu odwoływać się do wcześniejszej wartości w tym samym wyliczeniu ?
@ tgm1024 gcc -ansi -pedantic -Wallnie daje ostrzeżeń, więc ufam gcc; Jeśli to c89zadziała, to i tak powinno działać na dobre c99.
rrr
1
„Ponieważ fałsz ma tylko jedną wartość, ale logiczna prawda może mieć wiele wartości, ale technika ustawia prawdę na to, co kompilator użyje jako przeciwieństwo fałszu”. Operator negacji !może tylko zwracać wartości 0i 1dlatego true = !falsezawsze przypisuje wartość 1. Ta metoda nie zapewnia żadnego dodatkowego bezpieczeństwa typedef enum { false, true } bool;.
user694733,
1
Najwcześniej znalazłem z C90 (6.3.3.3 Unary arytmetyczne operatory): „Wynik logicznego operatora negacji! Wynosi 0, jeśli wartość jego argumentu jest nierówna do 0,1, jeśli wartość jego argumentu jest równa 0. wynik ma typ int. Wyrażenie! E jest równoważne (O == E). " Powinno to obejmować każdy kompilator, który kiedykolwiek twierdził, że obsługuje standard C. Kompilatory można oczywiście legalnie zignorować tę zasadę w przypadkach, gdy nie ma to znaczenia dla obserwowalnego zachowania (jak if(!value)), ale wyjątek ten nie ma zastosowania w tym konkretnym przypadku.
user694733,
48
Jeśli używasz kompilatora C99, ma on wbudowaną obsługę typów bool:
#include<stdbool.h>int main(){bool b =false;
b =true;}
Najpierw pierwsze. C, tj. ISO / IEC 9899 ma typ boolowski od 19 lat . To o wiele dłużej niż oczekiwana długość kariery programistycznej w C z amatorskimi / akademickimi / zawodowymi częściami połączonymi podczas odwiedzania tego pytania . Mój przewyższa to o zaledwie może 1-2 lata. Oznacza to, że w czasie , gdy przeciętny czytelnik w ogóle nauczył się czegoś o C, C faktycznie miał logiczny typ danych .
Dla typu danych, #include <stdbool.h>i wykorzystania true, falsea bool. Lub nie dołączaj go i używaj _Bool, 1a 0zamiast tego.
Istnieją różne niebezpieczne praktyki promowane w innych odpowiedziach na ten wątek. Zajmę się nimi:
typedefintbool;#definetrue1#definefalse0
Jest to nie-nie, ponieważ przypadkowy czytelnik - który nauczył się C w ciągu tych 19 lat - spodziewałby się, że boolodnosi się do faktycznegobool typu danych i zachowałby się podobnie, ale tak nie jest! Na przykład
double a =...;bool b = a;
W przypadku C99 bool/ _Bool, bwartość falseiff byłaby arówna zero, a truepoza tym. C11 6.3.1.2p1
Kiedy dowolna wartość skalarna jest konwertowana _Bool, wynikiem jest 0, jeśli wartość jest równa 0; w przeciwnym razie wynik to 1. 59)
Przypisy
59) NaN nie porównują równe 0, a zatem przeliczają na 1.
Z typedefna miejscu, doublebyłby zmuszony do int- jeżeli wartość podwójnej nie mieści się w zakresie do intThe zachowanie jest niezdefiniowane .
Oczywiście to samo dotyczy, jeśli truei falsezostały zadeklarowane w enum.
Jeszcze bardziej niebezpieczne jest deklarowanie
typedefenumbool{false,true}bool;
ponieważ teraz wszystkie wartości oprócz 1 i 0 są nieprawidłowe i gdyby taka wartość została przypisana do zmiennej tego typu, zachowanie byłoby całkowicie niezdefiniowane .
Dlatego jeśli nie możesz użyć C99 z jakiegoś niewytłumaczalnego powodu, dla zmiennych boolowskich powinieneś użyć:
typ inti wartości 0i 1jak jest ; i ostrożnie wykonuj konwersje domen z innych wartości na te z podwójną negacją!!
lub jeśli nalegasz , że nie pamiętasz, że 0 to fałsz i niezerowe truish, przynajmniej użyj wielkich liter , tak aby nie dostać mylić z pojęciami C99: BOOL, TRUEi FALSE!
Jaka część normy C ograniczyłaby obiekty wyliczonych typów do przechowywania wartości wyraźnie w nich wymienionych? Jeśli największa wartość wyliczonej stałej jest mniejsza niż UCHAR_MAX lub USHRT_MAX, implementacja może użyć typu mniejszego niż intlub unsigned intdo przechowywania wyliczenia, ale nie znam nic w standardzie, co spowodowałoby, że wyliczenie działałoby jak coś innego niż liczba całkowita rodzaj.
@technosaurus Takie podejście nie gwarantuje! false == true, ponieważ! false może być dowolną liczbą niezerową. Prostym obejściem byłoby jawne przypisanie wartości true do! False.
Andrew
3
@Andrew To nieprawda. !0 = 1według normy C i !a = 0dla dowolnej niezerowej wartości a. Problem polega na tym, że wszelkie niezerowe są uważane za prawdziwe. Więc jeśli ai boba są „prawdziwe”, niekoniecznie jest tak, że `a == b`.
Jeremy West,
14
C ma typ boolowski: bool (przynajmniej przez ostatnie 10 (!) Lat)
Dołącz stdbool.h, a true / false będzie działać zgodnie z oczekiwaniami.
10 lat w standardzie, ale nie 10 lat w kompilatorach! Kompilacja C MSVC ++ w ogóle nie obsługuje C99 poza dopuszczaniem // komentarzy i nigdy nie będzie tego robić. Również _Bool jest zdefiniowany w C99 jako typ wbudowany, podczas gdy bool jest typedef w nagłówku <stdbool.h>.
Clifford,
5
@Clifford 4 lata po twoim komentarzu ... nic się nie zmieniło. MSVC jest kompilatorem C ++ i wierzę, że MS powiedziało, że tak naprawdę nie chce obsługiwać wszystkich nowych funkcji C (C99 i C11). Ale nie mogę przyjąć, że MSVC nie obsługuje nowych funkcji C jako powodu (szczególnie, gdy mówisz to w ciągu 10 lat od odpowiedzi). 10 lat to naprawdę długi czas w świecie programowania. Każdy przyzwoity kompilator powinien mieć wsparcie w ciągu niecałych 10 lat, jeśli sprzedawca zamierza go obsługiwać.
PP
2
@KingsIndian: Nie jestem pewien, dlaczego skierowałeś swój komentarz do mnie, a nawet nie odczułem potrzeby komentowania. Podaję tylko sytuację, jaka była w momencie pisania. Nie popierałem tej sytuacji, wskazując jedynie, że „odpowiedź” może nie mieć zastosowania we wszystkich okolicznościach.
Clifford
@Clifford: Ściśle mówiąc, standard wymaga boolmakra, które rozwija się do _Bool. Różnica jest ważna, ponieważ możesz #undefmakra (i jest to dozwolone, przynajmniej jako środek przejściowy), ale nie możesz wpisać untypedefczcionki. Nie zmienia to jednak głównej myśli pierwszego komentarza.
Jonathan Leffler
2
VS2015 a następnie (i ewentualnie wcześniej, aż do punktu) mają żadnego problemu boolpoprzez <stdbool.h>zgodnie C kompilacji. To rozwiązuje _Bool.
11
Wszystkie niezerowe wartości są sprawdzane jako prawdziwe w operacjach boolowskich, więc możesz po prostu
ale używaj ich ostrożnie: ponieważ prawdziwy wynik może być dowolną wartością niezerową, testy if (t == TRUE) {...} i if (t), które są równoważne w innych językach, nie są równoważne w C .
Fortega
1
Masz rację, ale dotyczy to również C ++, które ma typ bool, prawda? Podczas debugowania widziałem zmienne bool o wartości 5837834939 ...
ggambett
1
W C ++ test if (t == true) równa się testowi if (t), ponieważ C ++ dokonuje pewnej konwersji (wszystko, co nie jest równe 0 lub wartość wskaźnika zerowego jest konwertowana na true)
Fortega
6
Wszystko, co powinieneś założyć o prawdziwej wartości logicznej, to to, że jest ona niezerowa. Więc kod jak jeśli (b) jest bezpieczny, podczas gdy if (b == PRAWDA) nie jest; ta ostatnia jest złą praktyką (i bez sensu).
Clifford,
5
Tylko uzupełnienie innych odpowiedzi i wyjaśnienie, jeśli możesz używać C99.
+-------+----------------+-------------------------+--------------------+|Name|Characteristic|Dependence in stdbool.h |Value|+-------+----------------+-------------------------+--------------------+|_Bool|Native type |Don't need header ||+-------+----------------+-------------------------+--------------------+|bool|Macro|Yes|Translate to _Bool|+-------+----------------+-------------------------+--------------------+|true|Macro|Yes|Translate to 1|+-------+----------------+-------------------------+--------------------+|false|Macro|Yes|Translate to 0|+-------+----------------+-------------------------+--------------------+
Niektóre z moich preferencji:
_Boolczy bool? Oba są w porządku, ale boolwyglądają lepiej niż słowo kluczowe_Bool .
Akceptowane wartości dla booli _Boolsą: falselub true. Przypisywanie 0lub 1zamiast falselub truejest poprawne, ale trudniej jest je odczytać i zrozumieć przepływ logiki.
Niektóre informacje ze standardu:
_BoolNIE jest unsigned int, ale należy do grup całkowitych bez znaku . Jest wystarczająco duży, aby pomieścić wartości 0lub1 .
NIE, ale tak, jesteś w stanie przedefiniować booltrueifalse pewno nie jest to dobry pomysł. Ta zdolność jest uważana za przestarzałą i zostanie usunięta w przyszłości.
Przypisanie typu skalarnego (typy arytmetyczne i typy wskaźników) do _Boollub bool, jeśli wartość skalarna jest równa 0lub 0będzie się z nią porównywać 0, w przeciwnym razie wynikiem jest 1: _Bool x = 9;9jest konwertowany na 1po przypisaniu x.
_Boolma 1 bajt (8 bitów), zwykle programiści kuszą, aby spróbować użyć innych bitów, ale nie jest to zalecane, ponieważ jedyną gwarancją jest to, że tylko jeden bit służy do przechowywania danych, a nie jak typ, charktóry ma 8 dostępne bity.
Również w C jest zwykle liczbą całkowitą i może powodować utratę precyzyjnych ostrzeżeń przez inny kod, który używa liczby wewnętrznej.
Thomas Bonini,
O ile nie optymalizujesz ręcznie pod kątem miejsca, zawsze lepiej jest użyć zwykłego rozmiaru słowa (np. Zwykle an int), ponieważ na niektórych architekturach znaczny spadek wydajności wynika z konieczności rozpakowywania / maskowania tych zmiennych.
Kingsley,
2
Możesz użyć _Bool, ale zwracana wartość musi być liczbą całkowitą (1 dla true, 0 dla false). Zaleca się jednak dołączenie i użycie bool jak w C ++, jak powiedziano w
tej odpowiedzi z forum daniweb , a także w tej odpowiedzi , z tego innego pytania dotyczącego przepełnienia stosu :
_Bool: typ logiczny C99. Bezpośrednie korzystanie z _Bool jest zalecane tylko wtedy, gdy utrzymujesz starszy kod, który już definiuje makra dla bool, true lub false. W przeciwnym razie te makra są znormalizowane w nagłówku. Dołącz ten nagłówek, a będziesz mógł używać bool tak samo jak w C ++.
Jeśli używasz C99, możesz użyć tego _Booltypu. Nie #includesą konieczne. Musisz jednak traktować to jak liczbę całkowitą, gdzie 1jest truei 0jest false.
Następnie możesz zdefiniować TRUEi FALSE.
_Bool this_is_a_Boolean_var =1;//or using it with true and false#define TRUE 1#define FALSE 0_Bool var = TRUE;
NOT makro powinny być chronione przez nawiasy wokół argi ekspresji jako całości #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE). Lepiej byłoby jednak sprawdzić pod kątem fałszu (da poprawną odpowiedź, nawet jeśli miałoby arg23 zamiast 0 lub 1: #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)Ale całe wyrażenie można #define NOT(arg) (!(arg))oczywiście sprowadzić do , co daje ten sam wynik)
Odpowiedzi:
Od najlepszych do gorszych:
Opcja 1 (C99)
Opcja 2
Opcja 3
Opcja 4
Wyjaśnienie
Jeśli nie jesteś zdecydowany, idź z numerem 1!
źródło
<stdbool.h>
bool
wybranego kompilatora mogą być bardziej odpowiednie do zamierzonego celu wartości boolowskiej niż wykorzystanieint
(tzn. kompilator może wybrać implementacjębool
inną niż anint
). Jeśli masz szczęście, może to również skutkować bardziej rygorystycznym sprawdzaniem typu w czasie kompilacji.int
zbool
? To marnotrawstwo. Zastosowanieunsigned char
. Lub użyj polecenie wbudowane c za_Bool
.Kilka przemyśleń na temat booleanów w C:
Jestem wystarczająco stary, że używam zwykłego
int
s jako mojego typu logicznego bez żadnych typedefs, specjalnych definicji lub wyliczeń dla wartości prawda / fałsz. Jeśli zastosujesz się do mojej poniższej sugestii, aby nigdy nie porównywać stałych stałych boolowskich, wystarczy użyć 0/1, aby zainicjować flagi. Takie podejście można jednak uznać za zbyt reakcyjne w dzisiejszych czasach. W takim przypadku należy zdecydowanie skorzystać,<stdbool.h>
ponieważ przynajmniej ma tę zaletę, że jest znormalizowana.Jakiekolwiek są stałe logiczne, używaj ich tylko do inicjalizacji. Nigdy nie pisz czegoś takiego
Zawsze można je zastąpić jaśniejszym
Pamiętaj, że można je właściwie odczytać na głos.
Nadaj swoim zmiennym logicznym pozytywne nazwy, tj
full
Zamiastnotfull
. Ten ostatni prowadzi do kodu, który jest trudny do odczytania. Porównaćz
Obie poprzednie pary czytają naturalnie, chociaż
!notfull
trudno jest je czytać w obecnej postaci, i stają się znacznie gorsze w bardziej złożonych wyrażeniach boolowskich.Ogólnie należy unikać argumentów logicznych. Rozważ funkcję zdefiniowaną w ten sposób
W treści funkcji jest bardzo jasne, co oznacza argument, ponieważ ma wygodną i, miejmy nadzieję, znaczącą nazwę. Ale wyglądają strony z połączeniami
W tym przypadku zasadniczo nie można powiedzieć, co oznacza parametr, nie zawsze patrząc na definicję lub deklarację funkcji, a staje się znacznie gorzej, gdy dodasz jeszcze więcej parametrów boolowskich. Sugeruję albo
lub
W obu przypadkach wygląda teraz strona połączeń
który czytelnik ma przynajmniej szansę na zrozumienie bez pogłębiania definicji
foo
.źródło
a == b
działa?a
ib
licząc od zera, poleciłbyma > 0 == b > 0
zamiast tego. Jeśli nalegasz na wykorzystanie prawdziwości arbitralnych niezerowych wartości, otrzymasz!!var
wartość logiczną 0/1 równąvar
, więc możesz napisać!!a == !!b
, chociaż wielu czytelników uzna to za mylące.!a == !b
jest również wystarczający do testowania równości, niezerowe stają się zerami, a zera stają się jednością.!!a
jako „przekonwertować wartość niebędącą boolowską na jej równoważną wartość prawdy”, podczas gdy przeczytałbym!a
jako „logicznie odwróć zmienną boolowską a”. W szczególności szukałem konkretnego powodu, dla którego logiczna inwersja była pożądana.Wartość logiczna w C jest liczbą całkowitą: zero dla wartości false i niezerowa dla wartości true.
Zobacz także typ danych logicznych , sekcja C, C ++, Objective-C, AWK .
źródło
Oto wersja, której użyłem:
Ponieważ fałsz ma tylko jedną wartość, ale logiczna prawda może mieć wiele wartości, ale technika ustawia true na to, co kompilator użyje w przeciwieństwie do fałszu.
To rozwiązuje problem z kodowaniem czegoś, co sprowadzałoby się do tego:
Myślę, że wszyscy zgodzilibyśmy się, że nie jest to dobra praktyka, ale jednorazowy koszt wykonania „prawda =! Fałsz” eliminujemy ten problem.
[EDYCJA] W końcu użyłem:
aby uniknąć kolizji nazw z innymi schematami, które definiowały
true
ifalse
. Ale koncepcja pozostaje taka sama.[EDYCJA] Aby wyświetlić konwersję liczby całkowitej na wartość logiczną:
Pierwszy (najbardziej odpowiedni)! konwertuje niezerową liczbę całkowitą na 0, a następnie drugą (najbardziej w lewo)! konwertuje 0 na a
myfalse
wartość. Zostawię to jako ćwiczenie dla czytelnika do konwersji zerowej liczby całkowitej.[EDYCJA] Moim stylem jest używanie jawnego ustawienia wartości w wyliczeniu, gdy wymagana jest konkretna wartość, nawet jeśli wartość domyślna byłaby taka sama. Przykład: Ponieważ fałsz musi wynosić zero, używam
false = 0,
raczej niżfalse,
źródło
true
,false
ibool
są podświetlone w większości IDE, ponieważ są wartości enum i typedef, w przeciwieństwie do#defines
, które są rzadko składnia podświetlona.gcc -ansi -pedantic -Wall
nie daje ostrzeżeń, więc ufamgcc
; Jeśli toc89
zadziała, to i tak powinno działać na dobrec99
.!
może tylko zwracać wartości0
i1
dlategotrue = !false
zawsze przypisuje wartość 1. Ta metoda nie zapewnia żadnego dodatkowego bezpieczeństwatypedef enum { false, true } bool;
.if(!value)
), ale wyjątek ten nie ma zastosowania w tym konkretnym przypadku.Jeśli używasz kompilatora C99, ma on wbudowaną obsługę typów bool:
http://en.wikipedia.org/wiki/Boolean_data_type
źródło
Najpierw pierwsze. C, tj. ISO / IEC 9899 ma typ boolowski od 19 lat . To o wiele dłużej niż oczekiwana długość kariery programistycznej w C z amatorskimi / akademickimi / zawodowymi częściami połączonymi podczas odwiedzania tego pytania . Mój przewyższa to o zaledwie może 1-2 lata. Oznacza to, że w czasie , gdy przeciętny czytelnik w ogóle nauczył się czegoś o C, C faktycznie miał logiczny typ danych .
Dla typu danych,
#include <stdbool.h>
i wykorzystaniatrue
,false
abool
. Lub nie dołączaj go i używaj_Bool
,1
a0
zamiast tego.Istnieją różne niebezpieczne praktyki promowane w innych odpowiedziach na ten wątek. Zajmę się nimi:
Jest to nie-nie, ponieważ przypadkowy czytelnik - który nauczył się C w ciągu tych 19 lat - spodziewałby się, że
bool
odnosi się do faktycznegobool
typu danych i zachowałby się podobnie, ale tak nie jest! Na przykładW przypadku C99
bool
/_Bool
,b
wartośćfalse
iff byłabya
równa zero, atrue
poza tym. C11 6.3.1.2p1Z
typedef
na miejscu,double
byłby zmuszony doint
- jeżeli wartość podwójnej nie mieści się w zakresie doint
The zachowanie jest niezdefiniowane .Oczywiście to samo dotyczy, jeśli
true
ifalse
zostały zadeklarowane wenum
.Jeszcze bardziej niebezpieczne jest deklarowanie
ponieważ teraz wszystkie wartości oprócz 1 i 0 są nieprawidłowe i gdyby taka wartość została przypisana do zmiennej tego typu, zachowanie byłoby całkowicie niezdefiniowane .
Dlatego jeśli nie możesz użyć C99 z jakiegoś niewytłumaczalnego powodu, dla zmiennych boolowskich powinieneś użyć:
int
i wartości0
i1
jak jest ; i ostrożnie wykonuj konwersje domen z innych wartości na te z podwójną negacją!!
BOOL
,TRUE
iFALSE
!źródło
int
lubunsigned int
do przechowywania wyliczenia, ale nie znam nic w standardzie, co spowodowałoby, że wyliczenie działałoby jak coś innego niż liczba całkowita rodzaj.źródło
!0 = 1
według normy C i!a = 0
dla dowolnej niezerowej wartościa
. Problem polega na tym, że wszelkie niezerowe są uważane za prawdziwe. Więc jeślia
ib
oba są „prawdziwe”, niekoniecznie jest tak, że `a == b`.C ma typ boolowski: bool (przynajmniej przez ostatnie 10 (!) Lat)
Dołącz stdbool.h, a true / false będzie działać zgodnie z oczekiwaniami.
źródło
bool
makra, które rozwija się do_Bool
. Różnica jest ważna, ponieważ możesz#undef
makra (i jest to dozwolone, przynajmniej jako środek przejściowy), ale nie możesz wpisaćuntypedef
czcionki. Nie zmienia to jednak głównej myśli pierwszego komentarza.bool
poprzez<stdbool.h>
zgodnie C kompilacji. To rozwiązuje_Bool
.Wszystkie niezerowe wartości są sprawdzane jako prawdziwe w operacjach boolowskich, więc możesz po prostu
i użyj stałych.
źródło
Tylko uzupełnienie innych odpowiedzi i wyjaśnienie, jeśli możesz używać C99.
Niektóre z moich preferencji:
_Bool
czybool
? Oba są w porządku, alebool
wyglądają lepiej niż słowo kluczowe_Bool
.bool
i_Bool
są:false
lubtrue
. Przypisywanie0
lub1
zamiastfalse
lubtrue
jest poprawne, ale trudniej jest je odczytać i zrozumieć przepływ logiki.Niektóre informacje ze standardu:
_Bool
NIE jestunsigned int
, ale należy do grup całkowitych bez znaku . Jest wystarczająco duży, aby pomieścić wartości0
lub1
.bool
true
ifalse
pewno nie jest to dobry pomysł. Ta zdolność jest uważana za przestarzałą i zostanie usunięta w przyszłości._Bool
lubbool
, jeśli wartość skalarna jest równa0
lub0
będzie się z nią porównywać0
, w przeciwnym razie wynikiem jest1
:_Bool x = 9;
9
jest konwertowany na1
po przypisaniux
._Bool
ma 1 bajt (8 bitów), zwykle programiści kuszą, aby spróbować użyć innych bitów, ale nie jest to zalecane, ponieważ jedyną gwarancją jest to, że tylko jeden bit służy do przechowywania danych, a nie jak typ,char
który ma 8 dostępne bity.źródło
To jest to:
źródło
Możesz użyć do tego znaku char lub innego kontenera o małej liczbie.
Pseudo kod
źródło
int
), ponieważ na niektórych architekturach znaczny spadek wydajności wynika z konieczności rozpakowywania / maskowania tych zmiennych.Możesz użyć _Bool, ale zwracana wartość musi być liczbą całkowitą (1 dla true, 0 dla false). Zaleca się jednak dołączenie i użycie bool jak w C ++, jak powiedziano w tej odpowiedzi z forum daniweb , a także w tej odpowiedzi , z tego innego pytania dotyczącego przepełnienia stosu :
źródło
Wyrażenia warunkowe są uważane za prawdziwe, jeśli są niezerowe, ale standard C wymaga, aby operatory logiczne same zwracały 0 lub 1.
@Tom: #define TRUE! FALSE jest zły i całkowicie bezcelowy. Jeśli plik nagłówkowy trafia do skompilowanego kodu C ++, może to prowadzić do problemów:
Niektóre kompilatory generują ostrzeżenie o konwersji int => bool. Czasami ludzie unikają tego, wykonując:
aby wymusić wyrażenie jako bool C ++. Ale jeśli zdefiniujesz PRAWDA! FAŁSZ, otrzymasz:
co kończy się porównywaniem wartości całkowitych, które i tak mogą wywołać ostrzeżenie.
źródło
Jeśli używasz C99, możesz użyć tego
_Bool
typu. Nie#include
są konieczne. Musisz jednak traktować to jak liczbę całkowitą, gdzie1
jesttrue
i0
jestfalse
.Następnie możesz zdefiniować
TRUE
iFALSE
.źródło
#include <stdbool.h>
i używaszbool
,true
ifalse
tak jak standard tego chce.Obecnie C99 obsługuje typy logiczne, ale musisz
#include <stdbool.h>
.Przykład:
Wynik:
źródło
Oto, czego używam:
_Bool
jest wbudowanym typem C. Jest przeznaczony do wartości boolowskich.źródło
Możesz po prostu użyć
#define
dyrektywy w następujący sposób:I użyj w następujący sposób:
i tak dalej
źródło
arg
i ekspresji jako całości#define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE)
. Lepiej byłoby jednak sprawdzić pod kątem fałszu (da poprawną odpowiedź, nawet jeśli miałobyarg
23 zamiast 0 lub 1:#define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)
Ale całe wyrażenie można#define NOT(arg) (!(arg))
oczywiście sprowadzić do , co daje ten sam wynik)