Czy bool jest rodzimym typem C?

265

Zauważyłem, że kod jądra Linux używa bool, ale myślałem, że bool był typem C ++. Czy bool jest standardowym rozszerzeniem C (np. ISO C90) czy rozszerzeniem GCC?

asussex
źródło
2
Sekcja 9 FAQ comp.lang.c omawia to.
Keith Thompson,
1
Bezpośredni link: c-faq.com/bool/index.html
Ellen Spertus
Używa jądra Linux, -std=gnu89które obsługuje _Booljako rozszerzenie do C90. „include / linux / types.h” ma typedef _Bool bool;.
Ian Abbott
Również FWIW, jądro Linuksa 2.6.19 było pierwszą wersją do użycia typedef _Bool bool;(commit 6e21828743247270d09a86756a0c11702500dbfb ) i wymagało GNU C 3.2 lub nowszego.
Ian Abbott

Odpowiedzi:

368

bool istnieje w obecnym C - C99, ale nie w C89 / 90.

W C99 wywoływany jest typ macierzysty _Bool, podczas gdy booljest to standardowe makro biblioteki zdefiniowane w stdbool.h(do którego oczekuje się _Bool). Obiektów typu _Boolzawieszone albo 0 albo 1, natomiast truei falsesą również z makr stdbool.h.

Zauważ, BTW, że oznacza to, że preprocesor C będzie interpretował #if truetak, jakby #if 0nie stdbool.hzostał uwzględniony. Tymczasem wymagany jest preprocesor C ++, aby natywnie rozpoznać trueliterał językowy.

Mrówka
źródło
62
Istnieje nowy standard ISO C, opublikowany w 2011 roku (po opublikowaniu tej odpowiedzi). ANSI, jak zwykle, przyjęła normę ISO C11 jako normę ANSI. Ze względów historycznych zwrot „ANSI C” często (ale niepoprawnie) odnosi się do języka zdefiniowanego w normie ANSI C89 / ISO C90. Ponieważ normy C są najpierw publikowane przez ISO, a ponieważ istnieją trzy normy ISO C o różnych poziomach przyjęcia, najlepiej odwołać się do roku, w którym norma została opublikowana (ISO C90, ISO C99, ISO C11), aby uniknąć jakichkolwiek dezorientacja.
Keith Thompson,
8
Czy to oznacza, że _Boolzajmuje 1 bit pamięci?
Geremia
27
@Geremia: Nie. Dlaczego? W C każdy obiekt adresowalny musi zajmować co najmniej 1 bajt. A w rzeczywistości implementacje _Boolzwykle zajmują 1 bajt pamięci. Jednak specyfikacja języka wyraźnie zezwala na użycie _Booljako typu pola bitowego, co oznacza, że ​​używając pól bitowych możesz wycisnąć _Boolwartość w pojedynczy bit (wewnątrz większej struktury).
AnT
@AnT W jaki sposób _Boolwartość może być bezpośrednio adresowalna (tzn. Rozmiar 1 bajtu), a także uczestniczyć w polu bitowym? Tablica _Boolnadal wymagałaby adresowania wszystkich swoich elementów (np _Bool* ptr = &boolArray[123].).
Dai
118

C99 dodał wbudowany _Booltyp danych ( szczegółowe informacje można znaleźć w Wikipedii ), a jeśli tak #include <stdbool.h>, udostępnia boolon makro jako _Bool.

Pytałeś w szczególności o jądro Linuksa. Zakłada obecność _Booli udostępnia boolsam typedef w include / linux / types.h .

Josh Kelley
źródło
26
Dlaczego ma to być niezdefiniowane i przedefiniowane tam, gdzie jego definicja może spowodować konflikt ze starszym kodem.
Clifford
32

Nie, nie ma go boolw ISO C90.

Oto lista słów kluczowych w standardzie C (nie C99):

  • auto
  • break
  • case
  • char
  • const
  • continue
  • default
  • do
  • double
  • else
  • enum
  • extern
  • float
  • for
  • goto
  • if
  • int
  • long
  • register
  • return
  • short
  • signed
  • static
  • struct
  • switch
  • typedef
  • union
  • unsigned
  • void
  • volatile
  • while

Oto artykuł omawiający inne różnice w C używane w jądrze i standardzie: http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/index.html

BobbyShaftoe
źródło
6
Czy dla celów praktycznych to naprawdę ma znaczenie, dopóki nie ma przyzwoitej obsługi kompilatora? Nawet gcc nie miał do niedawna połowy funkcji C99, a MSVC nie ma większości z nich i prawdopodobnie nigdy nie będzie ...
Pavel Minaev
5
@Jonathan Leffler, pytający konkretnie zapytał o ISO C90. :) W rzeczywistości, zwykle gdy ludzie odnoszą się do ANSI C, to znaczy C90. Nie używam ani nie planuję używać C99 i myślę, że wielu czuje to samo.
BobbyShaftoe
6
@BobbyShaftoe: Oryginalny plakat wyraźnie stwierdził w komentarzu, że C90 był przykładem.
Keith Thompson,
32

C99 ma go w stdbool.h , ale w C90 musi być zdefiniowany jako typedef lub enum:

typedef int bool;
#define TRUE  1
#define FALSE 0

bool f = FALSE;
if (f) { ... }

Alternatywnie:

typedef enum { FALSE, TRUE } boolean;

boolean b = FALSE;
if (b) { ... }
Obrabować
źródło
5
Zauważ, że zachowanie typedef będzie inne niż zachowanie C99 bool, a także inne niż zachowanie wielu bittypów kompilatorów . Na przykład, bool x=4294967296LL;czy bool x=0.1;będzie ustawiony xna jeden z C99, ale najprawdopodobniej ustawiony wersje najbardziej typedef do zera.
supercat
17
/* Many years ago, when the earth was still cooling, we used this: */

typedef enum
{
    false = ( 1 == 0 ),
    true = ( ! false )
} bool;

/* It has always worked for me. */
użytkownik2705144
źródło
16
Początkowe wartości są całkowicie niepotrzebne. typedef enum { false, true };jest tak samo dobry. Jeśli nalegasz, aby być bardziej wyraźnym, możesz pisać typedef enum { false = 0, true = 1 };. (Lub tylko #include <stdbool.h>jeśli twój kompilator to obsługuje; jest to standard od 14 lat.)
Keith Thompson
9
@KeithThompson Wartości początkowe mogą być niepotrzebne, ale ta odpowiedź wybiera je w bardzo elegancki sposób, nie z dowolnymi wartościami, ale z wykorzystaniem własnej semantyki języków i pozwalając kompilatorowi decydować.
MestreLion
11
@MestreLion: własna semantyka języka gwarantuje, że typedef enum { false, true } bool;działa dokładnie zgodnie z oczekiwaniami. 1 == 0i ! falsenie są eleganckie, są jedynie zaciemnione. Kompilator nie musi podjąć żadnej decyzji; musi przestrzegać semantyki określonej przez język.
Keith Thompson
11
@KeithThompson: Nie sądzę, aby były zaciemnione, myślę, że intencją autora było wybranie najbardziej „naturalnych” wartości: falsejest ustawiony na dowolną wartość, jaką według języka należy oceniać nierówność, i truena „przeciwne” ( ponownie, cokolwiek to jest). W ten sposób nie powinno nas obchodzić, czy to {1, 0}, {-1, 0}, {0, 1} itd., I gwarantujemy, że będzie działało w porównaniach, ponieważ zostało stworzone przy użyciu jednego.
MestreLion
3
@MestreLion: Każdy, kto zna C, zna wartości liczbowe falsei true. Każdy, kto nie zna C, nie jest oczekiwanym odbiorcą kodu C. I jak powiedziałem, C ma wbudowany typ boolowski od poprzedniego tysiąclecia.
Keith Thompson
12

_Booljest słowem kluczowym w C99: określa typ, podobnie jak intlub double.

6.5.2

2 Obiekt zadeklarowany jako typ _Bool jest wystarczająco duży, aby przechowywać wartości 0 i 1.

pmg
źródło
6

C99 definiuje bool truei falsein stdbool.h.

starblue
źródło
2

stdbool.h został wprowadzony w c99

Nick Van Brunt
źródło
1

stdbool.h definiuje makra prawda i fałsz, ale pamiętaj, że zdefiniowano je jako 1 i 0.

Dlatego sizeof(true)jest 4.

Neha Gangwar
źródło
0

Nic takiego, prawdopodobnie tylko makro dla int

Sindre J.
źródło
Nieźle
5
cóż, mówi standard C np. C90, zakładam, że obejmuje C99.
Matt Joiner
2
Wspomina on o C90 w sposób szczególny, a NIE o C99, więc zakładam, że o to mu chodzi. Według wikipedii jedynym kompilatorem w pełni obsługującym C99 jest Sun Studio firmy Sun Microsystems. Czy to nie jest tak powszechnie akceptowany standard? Prawdopodobnie większość współczesnych kompilatorów implementuje części standardu C99. Powinienem chyba wspomnieć, że aby uniknąć głupich komentarzy takich jak twoje! Co java lub c # zrobić z tym Btw?
sindre j
8
standardowe rozszerzenie C (np. ISO C90) klasyfikuje rodzaj standardów C, którymi jest zainteresowany, a nie sam C90. odpowiednia odpowiedź na to pytanie jest tak C standardowe takie jak C90, C99 specjalnie średnia, ma realizować booltypu.
Matt Joiner
0

C99 dodał booltyp, którego semantyka jest zasadniczo różna od semantyki prawie wszystkich typów całkowitych, które istniały wcześniej w C, w tym typów zdefiniowanych przez użytkownika i rozszerzeń kompilatora przeznaczonych do takich celów, i które niektóre programy mogą mieć ed do bool.

Na przykład, biorąc pod uwagę bool a = 0.1, b=2, c=255, d=256;, booltyp C99 ustawi wszystkie cztery obiekty na 1. Jeśli użyty zostanie program C89 typedef unsigned char bool, obiekty otrzymają odpowiednio 0, 1, 255 i 0. Jeśli zostanie użyty char, wartości mogą być takie jak powyżej lub cmogą wynosić -1. Gdyby użył rozszerzenia bitlub __bittypu kompilatora , wyniki prawdopodobnie wynosiłyby 0, 0, 1, 0 (traktowanie bitw sposób równoważny z niepodpisanym polem bitowym o rozmiarze 1 lub bez znaku liczby całkowitej z jednym bitem wartości).

supercat
źródło