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
.
Ответ 3
Логическое значение в C - целое число: ноль для false и ненулевое значение для true.
См. также Тип данных Boolean, раздел C, С++, Objective-C, AWK.
Ответ 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;
}
Ответ 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);
и так.. в