Использование булевых значений в C

C не имеет встроенных булевых типов. Какой лучший способ использовать их в C?

Ответ 1

От лучшего к худшему:

Вариант 1 (С99)

#include <stdbool.h>

Вариант 2

typedef enum { false, true } bool;

Вариант 3

typedef int bool;
enum { false, true };

Вариант 4

typedef int bool;
#define true 1
#define false 0

объяснение

  • Вариант 1 будет работать, только если вы используете C99, и это "стандартный способ" сделать это. Выберите это, если это возможно.
  • Варианты 2, 3 и 4 будут иметь на практике одинаковое поведение. # 2 и # 3 не используют #defines, что, на мой взгляд, лучше.

Если вы не определились, идите С# 1!

Ответ 2

Несколько мыслей о логических значениях в C:

Я достаточно взрослый, чтобы просто использовать в качестве логического типа plain int без каких-либо определений типов, специальных определений или перечислений для значений true/false. Если вы последуете моему предложению никогда не сравнивать с булевыми константами, тогда вам все равно нужно будет использовать 0/1 для инициализации флагов. Однако такой подход может считаться слишком реакционным в наше современное время. В этом случае определенно следует использовать <stdbool.h> поскольку он, по крайней мере, имеет преимущество от стандартизации.

Какие бы логические константы ни назывались, используйте их только для инициализации. Никогда не пиши что-то вроде

if (ready == TRUE) ...
while (empty == FALSE) ...

Они всегда могут быть заменены на более четкие

if (ready) ...
while (!empty) ...

Обратите внимание, что они могут быть разумно и понятно прочитаны вслух.

Дайте вашим логическим переменным положительные имена, то есть full вместо notfull. Последнее приводит к коду, который трудно прочитать легко. сравнить

if (full) ...
if (!full) ...

с

if (!notfull) ...
if (notfull) ...

Обе из первой пары читаются естественным образом, в то время как !notfull неудобно читать даже в том виде, как он есть, и становится намного хуже в более сложных логических выражениях.

Обычно следует избегать логических аргументов. Рассмотрим функцию, определенную следующим образом

void foo(bool option) { ... }

В теле функции очень ясно, что означает аргумент, поскольку он имеет удобное и, мы надеемся, содержательное имя. Но сайты вызова выглядят так

foo(TRUE);
foo(FALSE):

Здесь, по сути, невозможно сказать, что имел в виду параметр, не всегда просматривая определение или объявление функции, и становится намного хуже, как только вы добавляете еще больше логических параметров. Я предлагаю либо

typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);

или же

#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }

В любом случае сайт вызова теперь выглядит так

foo(OPT_ON);
foo(OPT_OFF);

что у читателя есть хотя бы шанс понять, не углубляясь в определение foo.

Ответ 4

Вот версия, которую я использовал:

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

Потому что false имеет только одно значение, но логическое true может иметь много значений, но метод устанавливает true, чтобы компилятор использовал противоположное false.

Это решает проблему того, что кто-то кодирует что-то, что сводится к этому:

if (true == !false)

Я думаю, что мы все согласны с тем, что это не очень хорошая практика, но за единовременную стоимость выполнения "true =! false" мы устраняем эту проблему.

[EDIT] В конце концов, я использовал:

typedef enum { myfalse = 0, mytrue = !myfalse } mybool;

чтобы избежать конфликта имен с другими схемами, которые определяли true и false. Но концепция остается прежней.

[РЕДАКТИРОВАТЬ] Чтобы показать преобразование целого числа в логическое значение:

mybool somebool;
int someint = 5;
somebool = !!someint;

Первый (самый правый)! преобразует ненулевое целое число в 0, затем второе (самое левое)! преобразует 0 в значение myfalse. Я оставлю читателю в качестве упражнения преобразование нулевого целого числа.

[РЕДАКТИРОВАТЬ] Мой стиль - использовать явную установку значения в перечислении, когда требуется конкретное значение, даже если значение по умолчанию будет таким же. Пример: поскольку false должно быть равно нулю, я использую false = 0,, а не false,

Ответ 5

Если вы используете компилятор C99, у него есть встроенная поддержка типов bool:

#include <stdbool.h>
int main()
{
  bool b = false;
  b = true;
}

http://en.wikipedia.org/wiki/Boolean_data_type

Ответ 6

Обо всем по порядку. C, то есть ISO/IEC 9899 имеет логический тип в течение 19 лет. Это намного больше времени, чем ожидаемая продолжительность карьеры программиста на C, когда любительские/академические/профессиональные части объединяются при посещении этого вопроса. Моя превосходит это всего лишь на 1-2 года. Это означает, что в то время, когда среднестатистический читатель вообще что-то узнал о C, C фактически имел логический тип данных.

Для типа данных #include <stdbool.h> используйте true, false и bool. Или не включайте его, а используйте вместо него _Bool, 1 и 0.


В этой ветке ответов есть различные опасные советы. Я обращусь к ним:

typedef int bool;
#define true 1
#define false 0

Это нет-нет, потому что случайный читатель - который изучил C в течение этих 19 лет - ожидал, что bool ссылается на фактический bool тип данных и будет вести себя аналогично, но Это не так! Например,

double a = ...;
bool b = a;

С C99 bool/_Bool для b будет установлено значение false тогда и только тогда, когда a будет равен нулю, а true в противном случае. С typedef на месте, double будет приведен к int - если значение double не находится в диапазоне для int, поведение не определено.

Естественно, то же самое относится к тому, если true и false были объявлены в enum.

Что еще опаснее, так и декларируется

typedef enum bool {
    false, true
} bool;

потому что теперь все значения, кроме 1 и 0, недопустимы, и если такое значение будет присвоено переменной этого типа, поведение будет полностью неопределенным.

Поэтому если вы не можете использовать C99 по какой-то необъяснимой причине, для логических переменных вы должны использовать:

  • введите int и значения 0 и 1 как есть; и тщательно выполняйте преобразования доменов из любых других значений в них с двойным отрицанием !!
  • или если вы настаиваете, то не помните, что 0 - это ложь и ненулевое значение, по крайней мере используйте верхний регистр, чтобы их не спутали с концепциями C99: BOOL, TRUE и FALSE!

Ответ 7

typedef enum {
    false = 0,
    true
} t_bool;

Ответ 8

C имеет булевский тип: bool (по крайней мере, за последние 10 (!) лет)

Включить stdbool.h и true/false будет работать как ожидалось.

Ответ 9

Любое ненулевое значение вычисляется как true в булевых операциях, поэтому вы можете просто

#define TRUE 1
#define FALSE 0

и используйте константы.

Ответ 10

Просто дополнение к другим ответам и некоторым разъяснениям, если вам разрешено использовать 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   |
+-------+----------------+-------------------------+--------------------+

Некоторые из моих предпочтений:

  • _Bool или bool? Оба в порядке, но bool выглядит лучше, чем ключевое слово _Bool.
  • Допустимые значения для bool и _Bool: false или true. Назначение 0 или 1 вместо false или true допустимо, но сложнее для чтения и понимания логического потока.

Некоторая информация из стандарта:

  • _Bool НЕ является unsigned int, но является частью группы целочисленных типов без знака. Он достаточно большой, чтобы содержать значения 0 или 1.
  • НЕ, но да, вы можете переопределить bool true и false но это не очень хорошая идея. Эта способность считается устаревшей и будет удалена в будущем.
  • Назначение скалярного типа (арифметических типов и типов указателей) для _Bool или bool, если скалярное значение равно 0 или сравнивается с 0 оно будет равно 0, в противном случае результат будет 1: _Bool x = 9; 9 преобразуется в 1 когда присваивается x.
  • _Bool - это 1 байт (8 бит), обычно у программиста возникает соблазн попытаться использовать другие биты, но это не рекомендуется, поскольку гарантируется только то, что для хранения данных используется только один бит, а не тип char который есть 8 бит доступны.

Ответ 11

@Thomas Matthews: условные выражения считаются истинными, если они отличны от нуля, но для стандарта C требуется, чтобы сами логические операторы возвращали либо 0, либо 1.

@Tom: #define TRUE! FALSE является плохим и совершенно бессмысленным. Если заголовочный файл входит в скомпилированный код на С++, это может привести к проблемам:

void foo(bool flag);

...

int flag = TRUE;
foo(flag);

Некоторые компиляторы будут генерировать предупреждение о преобразовании int = > bool. Иногда люди избегают этого, делая:

foo(flag == TRUE);

чтобы заставить выражение быть С++ bool. Но если вы #define TRUE! FALSE, вы получите:

foo(flag == !0);

который заканчивает выполнение сравнения int-to-bool, которое может вызвать предупреждение в любом случае.

Ответ 12

Вы можете использовать символ или другой контейнер с небольшим числом для него.

Псевдо-код

#define TRUE  1
#define FALSE 0

char bValue = TRUE;

Ответ 13

Это:

#define TRUE 1
#define FALSE 0

Ответ 14

Вы можете использовать _Bool, но возвращаемое значение должно быть целым числом (1 для true, 0 для false). Тем не менее, он рекомендовал включить и использовать bool, как в C++, как сказано в этом ответе на форуме daniweb, а также в этом ответе на этот другой вопрос stackoverflow:

_Bool: C99 логический тип. Использование _Bool напрямую рекомендуется только в том случае, если вы поддерживаете устаревший код, который уже определяет макросы для bool, true или false. В противном случае эти макросы стандартизированы в заголовке. Включите этот заголовок, и вы можете использовать bool так же, как и в C++.

Ответ 15

Если вы используете c99, вы можете использовать тип _Book, который является частью c99, т.е. нет необходимости в #includes. Вам нужно обращаться с ним как с int, где 1 = true, а 0 = false. Затем вы можете определить ИСТИНА и ЛОЖЬ.

_Bool this_is_a_Boolean_var = 1;


//or using it with true and false
#define TRUE 1
#define FALSE 0
_Book var = TRUE;

Ответ 16

Вы можете просто использовать директиву #define следующим образом:

#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;

И используйте следующее:

bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);

и так.. в