Чи є bool рідним типом С?


265

Я помітив, що код ядра Linux використовує bool, але подумав, що bool - це тип C ++. Чи є стандарт bool розширенням C (наприклад, ISO C90) або розширенням GCC?


2
Розділ 9 поширених запитань на comp.lang.c обговорює це.
Кіт Томпсон

1
Пряме посилання: c-faq.com/bool/index.html
Еллен Спертус

Ядро Linux використовує -std=gnu89підтримку _Boolяк розширення до C90. "include / linux / types.h" має typedef _Bool bool;.
Ян Абботт

Крім того, FWIW, ядро ​​Linux 2.6.19 було першою версією, яка використовувалась typedef _Bool bool;( призначати 6e21828743247270d09a86756a0c11702500dbfb ), і для цього потрібен GNU C 3.2 або пізнішої версії.
Ян Абботт

Відповіді:


368

bool існує в поточному C - C99, але не в C89 / 90.

У C99 власне тип власне називається _Bool, а boolстандартний макрос бібліотеки, визначений у stdbool.h(який, як очікується, вирішує _Bool). Об'єкти типу _Boolутримання 0 або 1, в той час як trueі falseтакож макроси з stdbool.h.

Зауважте, BTW, що це означає, що препроцесор C буде інтерпретувати так, #if trueяк #if 0не stdbool.hвключено. Тим часом, C ++-препроцесор необхідний для початкового розпізнавання trueмови.


62
Існує новий стандарт ISO C, опублікований у 2011 році (після опублікування цієї відповіді). ANSI, як завжди, прийняв стандарт ISO C11 як стандарт ANSI. З історичних причин словосполучення "ANSI C" зазвичай (але невідповідно) стосується мови, визначеної стандартом ANSI C89 / ISO C90. Оскільки стандарти стандарту C тепер опубліковані першими ISO, а оскільки існували три стандарти ISO C, з різним рівнем прийняття, найкраще звернутися до року опублікування стандарту (ISO C90, ISO C99, ISO C11), щоб уникнути будь-якого спантеличеність.
Кіт Томпсон

8
Це означає, що _Boolзаймає 1 біт пам'яті?
Геремія

27
@ Геремія: Ні. Чому? У C кожен адресований об'єкт повинен займати щонайменше 1 байт. А в реальному житті реалізація _Boolзазвичай займає 1 байт пам'яті. Однак специфікація мови явно дозволяє використовувати _Boolяк тип бітового поля, тобто, використовуючи бітові поля, ви можете видавити _Boolзначення в один біт (всередині більшої структури).
1616

@AnT Як _Boolзначення може бути як безпосередньо адресованим (тобто розміром 1 байт), так і брати участь у бітовому полі? Масив _Boolвсе-таки вимагатиме адреси всіх його елементів (наприклад _Bool* ptr = &boolArray[123]).
Дай

118

C99 додав вбудований _Boolтип даних (докладні відомості див. У Вікіпедії ), і якщо ви #include <stdbool.h>, це надає boolяк макрос _Bool.

Ви запитували зокрема про ядро ​​Linux. Він передбачає наявність _Boolі надає себе booltypedef в include / linux / types.h .


26
Щодо того, це дозволити, щоб воно не було визначене та переосмислене там, де його визначення може спричинити зіткнення зі застарілим кодом.
Кліффорд

32

Ні, boolв ISO C90 немає.

Ось перелік ключових слів у стандартній C (не 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

Ось стаття, де обговорюються деякі інші відмінності з C, як використовується в ядрі та стандарті: http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/index.html


6
З практичних цілей, чи це насправді так важливо, поки ще немає гідної підтримки компілятора? Навіть у gcc до недавнього часу не було половини функцій C99, а MSVC не має більшості з них, і, мабуть, ніколи не буде ...
Павло Мінаєв

5
@ Джонатан Леффлер, запитувач спеціально запитав про ISO C90. :) Насправді, зазвичай, коли люди посилаються на ANSI C, вони meaqn C90. Я не використовую або дійсно не планую використовувати C99, і я думаю, що багато хто відчуває те саме.
BobbyShaftoe

6
@BobbyShaftoe: Оригінальний плакат прямо в коментарі сказав, що C90 є прикладом.
Кіт Томпсон

32

У C99 він є в stdbool.h , але в C90 він повинен бути визначений як typedef або enum:

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

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

Як варіант:

typedef enum { FALSE, TRUE } boolean;

boolean b = FALSE;
if (b) { ... }

5
Зауважте, що поведінка typedef буде відрізнятися від поведінки C99 bool, а також відрізнятиметься від поведінки багатьох bitтипів компіляторів . Наприклад, bool x=4294967296LL;або bool x=0.1;встановив xби один на C99, але, ймовірно, встановить більшість версій typedef до нуля.
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. */

16
Початкові значення абсолютно не потрібні. typedef enum { false, true };так само добре. Якщо ви наполягаєте на тому, щоб бути більш чітким, ви можете написати typedef enum { false = 0, true = 1 };. (Або просто, #include <stdbool.h>якщо ваш компілятор підтримує це; це було стандартно протягом 14 років.)
Кіт Томпсон,

9
@KeithThompson Початкові значення можуть бути непотрібними, але ця відповідь вибирає їх дуже елегантно, не з довільними значеннями, а використовуючи власну семантику мов і дозволяючи компілятору приймати рішення.
MestreLion

11
@MestreLion: власна семантика мови гарантує typedef enum { false, true } bool;роботу точно так, як очікувалося. 1 == 0і ! falseне елегантні, вони просто затуманені. Компілятор не може прийняти рішення; вона повинна підкорятися семантиці, визначеній мовою.
Кіт Томпсон

11
@KeithThompson: Я не думаю, що вони заплутані, я думаю, що авторський намір полягав у виборі найбільш "природних" значень: falseвстановлюється будь-яке значення, за яким мова говорить, що нерівність повинна оцінюватися і true"її протилежність" ( знову, що б там не було). Таким чином не варто дбати, чи це {1, 0}, {-1, 0}, {0, 1} тощо, і це гарантовано працює у порівняннях, оскільки це було створено за допомогою одного.
MestreLion

3
@MestreLion: Кожен, хто знає C, знає числові значення falseі і true. Кожен, хто не знає C, не є очікуваною аудиторією для коду С. І, як я вже говорив, C мав бульовий тип з попереднього тисячоліття.
Кіт Томпсон

12

_Boolє ключовим словом у C99: він визначає тип, як intі double.

6.5.2

2 Об'єкт, оголошений як тип _Bool, досить великий, щоб зберігати значення 0 і 1.




1

stdbool.h визначає макроси істинні та хибні, але пам’ятайте, що вони визначені як 1 та 0.

Ось чому sizeof(true)4.


0

Немає такого, мабуть, лише макрос для int


Приємно з -1-м ... питання було C90, а не 99 я вважаю
sindre j

5
добре він каже, що стандарт C, наприклад, C90, я припускаю, що він включає C99.
Метт Столяр

2
Він спеціально згадує C90, а не C99, тому я припускаю, що він має на увазі. Згідно з wikipedia, єдиним компілятором, який повністю підтримує C99, є Sun Studio від Sun Microsystems. Зараз це навряд чи широко прийнятий стандарт? Напевно, більшість сучасних компіляторів НЕ реалізують частини стандарту C99, я, мабуть, зазначив, що уникати дурних коментарів, як ваш! Що java чи c # робити з цим btw?
sindre j

8
стандартне розширення C (наприклад, ISO C90) класифікує тип стандартів C, який його цікавить, а не конкретно сам C90. відповідний відповідь на це, так З стандарт , такі як C90, в зокрема , стандарт C99, це реалізувати boolтип.
Метт Столяр

0

C99 додав boolтип, семантика якого принципово відрізняється від того, що стосується майже всіх цілих типів, які існували раніше в C, включаючи визначені користувачем типи та розширення компілятора, призначені для таких цілей, і які деякі програми можуть мати "type-def" ed до bool.

Наприклад, заданий тип bool a = 0.1, b=2, c=255, d=256;C99 boolвстановив би всі чотири об'єкти на 1. Якщо використовується програма C89 typedef unsigned char bool, об'єкти отримали б відповідно 0, 1, 255 та 0. Якщо він використовується char, значення можуть бути такими, як вище, або cможуть бути -1. Якби він використовував компілятор-розширення bitабо __bitтип, результати, ймовірно, будуть 0, 0, 1, 0 (обробляючи bitспособом, еквівалентним неподписаному бітовому полі розміром 1, або непідписаним цілим числом з одним бітом значення).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.