Bool является родным типом C?


265

Я заметил, что код ядра Linux использует bool, но я подумал, что bool - это тип C ++. Является ли bool стандартным расширением C (например, ISO C90) или расширением GCC?


2
Раздел 9 FAQ по comp.lang.c обсуждает это.
Кит Томпсон


Ядро Linux использует -std=gnu89который поддерживает _Boolкак расширение C90. "include / linux / types.h" имеет typedef _Bool bool;.
Ян Эбботт

Кроме того, FWIW, ядро ​​Linux 2.6.19 было первой версией, которая использовала typedef _Bool bool;(commit 6e21828743247270d09a86756a0c11702500dbfb ) и требовала GNU C 3.2 или более поздней версии .
Ян Эбботт

Ответы:


368

bool существует в текущем C - C99, но не в C89 / 90.

В C99 фактически вызывается нативный тип _Bool, в то время boolкак это стандартный библиотечный макрос, определенный в stdbool.h(который, как ожидается, разрешается _Bool). Объекты типа _Boolсодержат 0 или 1, а также trueи falseявляются макросами из stdbool.h.

Обратите внимание, что это означает, что препроцессор 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
@ Geremia: Нет. Почему? В C каждый адресуемый объект должен занимать как минимум 1 байт. А в реальной жизни реализация _Boolобычно занимает 1 байт памяти. Однако спецификация языка явно разрешает использование в _Boolкачестве типа битовых полей, что означает, что с помощью битовых полей вы можете сжать _Boolзначение в один бит (внутри большей структуры).
AnT

@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, они имеют в виду 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 на ноль.
суперкат

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 Начальные значения могут быть ненужными, но этот ответ выбирает их очень элегантным способом, не с произвольными значениями, а с использованием собственной семантики языков и предоставлением возможности компилятору.
МестреЛион

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

11
@KeithThompson: я не думаю, что они запутаны, я предполагаю, что намерение автора состояло в том, чтобы выбрать наиболее "естественные" значения: falseустановлено любое значение, согласно которому язык должен оценивать неравенство, и trueего "противоположность" ( опять же, что бы это ни было). Таким образом, не нужно заботиться, если это {1, 0}, {-1, 0}, {0, 1} и т. Д., И он гарантированно будет работать в сравнениях, потому что он был создан с использованием единицы.
МестреЛион

3
@MestreLion: Любой, кто знает C, знает числовые значения falseи true. Тот, кто не знает C, не является ожидаемой аудиторией для C-кода. И, как я уже сказал, C имеет встроенный логический тип с прошлого тысячелетия.
Кит Томпсон

12

_Boolэто ключевое слово в C99: оно определяет тип, как intили double.

6.5.2

2 Объект, объявленный как тип _Bool, достаточно велик для хранения значений 0 и 1.




1

stdbool.h определяет макросы true и false, но помните, что они определены как 1 и 0.

Вот почему sizeof(true)4.


0

Нет такой вещи, вероятно, просто макрос для int


Хорошо с -1 ... вопрос был C90, а не 99, я верю
Синдр J

5
ну, он говорит, что стандарт C, например, C90, я предполагаю, что включает в себя C99.
Мэтт Джоунер

2
В частности, он упоминает С90, а не С99, поэтому я предполагаю, что он имеет в виду. Согласно википедии, единственным компилятором, который полностью поддерживает C99, является Sun Studio от Sun Microsystems. Так вот, вряд ли это общепринятый стандарт? Возможно, большинство современных компиляторов реализуют части стандарта C99, я должен был бы упомянуть это, чтобы избежать глупых комментариев, подобных вашему! Что делать Java или C # с этим кстати?
Синдр J

8
Стандартное расширение C (например, ISO C90) классифицирует интересующие его стандарты C, а не конкретно сам C90. соответствующий ответ на этот вопрос - да, стандарт C, такой как C90, в частности стандарт C99, действительно реализует boolтип.
Мэтт Джойнер

0

В C99 добавлен boolтип, семантика которого принципиально отличается от таковых практически всех целочисленных типов, которые существовали ранее в C, включая определяемые пользователем типы и расширения компилятора, предназначенные для таких целей, и которые некоторые программы могут иметь «type-def» ed к bool.

Например, учитывая bool a = 0.1, b=2, c=255, d=256;, что boolтип C99 установит все четыре объекта на 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.