Ответы:
Этот подход будет использовать фактический boolean
тип (и разрешать true
и false
), если его поддерживает компилятор. (в частности, C ++)
Однако было бы лучше проверить, используется ли C ++ (с помощью __cplusplus
макроса), и использовать на самом деле true
и false
.
В компиляторе C это эквивалентно 0
и 1
.
(обратите внимание, что удаление скобок нарушит порядок операций)
1==1
является int
. (см. stackoverflow.com/questions/7687403/… .)
boolean
типом?
true
или false
.
#define TRUE true
и #define FALSE false
всякий раз , когда __cplusplus
определяется.
Ответ - мобильность. Числовые значения TRUE
и FALSE
не важны. Что является важным является то , что такое заявление имеет if (1 < 2)
значение if (TRUE)
и заявление , как имеет if (1 > 2)
значение if (FALSE)
.
Конечно, в C он (1 < 2)
оценивает 1
и (1 > 2)
оценивает 0
, так что, как говорили другие, нет никакой практической разницы в том, что касается компилятора. Но позволяя компилятору определять TRUE
и в FALSE
соответствии с его собственными правилами, вы делаете их значения явными для программистов и гарантируете согласованность в своей программе и любой другой библиотеке (при условии, что другая библиотека соответствует стандартам C ... вы бы удивляться)
Немного истории
Некоторые бейсики определены FALSE
как 0
и TRUE
как -1
. Как и многие современные языки, они интерпретировали любое ненулевое значение как TRUE
, но они оценивали логические выражения, которые были истинными как -1
. Их NOT
работа была реализована путем добавления 1 и переключения знака, потому что это было эффективно сделать таким образом. Так что «НЕ х» стало -(x+1)
. Побочным эффектом этого является то, что значение как 5
оценивает TRUE
, но NOT 5
оценивает -6
, что также TRUE
! Находить такого рода ошибку не весело.
Наилучшие практики.
Учитывая фактические правила, что ноль интерпретируется как, FALSE
а любое ненулевое значение интерпретируется как TRUE
, вы никогда неTRUE
FALSE
должны сравнивать логически выглядящие выражения с или . Примеры:
if (thisValue == FALSE) // Don't do this!
if (thatValue == TRUE) // Or this!
if (otherValue != TRUE) // Whatever you do, don't do this!
Зачем? Потому что многие программисты используют ярлык для обработки int
s как bool
s. Они не одинаковы, но компиляторы обычно позволяют это. Так, например, совершенно законно писать
if (strcmp(yourString, myString) == TRUE) // Wrong!!!
Это выглядит законно, и компилятор с радостью примет это, но, вероятно, не будет делать то, что вы хотите. Это потому , что возвращаемое значение strcmp()
IS
0 если yourString == myString
<0 если yourString < myString
> 0 еслиyourString > myString
Таким образом, строка выше возвращается TRUE
только тогда, когда yourString > myString
.
Правильный способ сделать это либо
// Valid, but still treats int as bool.
if (strcmp(yourString, myString))
или
// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)
Так же:
if (someBoolValue == FALSE) // Redundant.
if (!someBoolValue) // Better.
return (x > 0) ? TRUE : FALSE; // You're fired.
return (x > 0); // Simpler, clearer, correct.
if (ptr == NULL) // Perfect: compares pointers.
if (!ptr) // Sleazy, but short and valid.
if (ptr == FALSE) // Whatisthisidonteven.
Некоторые из этих «плохих примеров» вы часто найдете в рабочем коде, и многие опытные программисты клянутся ими: они работают, некоторые короче, чем их (педантично?) Правильные альтернативы, и идиомы почти повсеместно признаны. Но учтите: «правильные» версии не менее эффективны, они гарантированно переносимы, они будут проходить даже самые строгие линтеры, и даже новые программисты поймут их.
Разве это не стоит того?
(1==1)
не более портативный, чем 1
. Собственные правила компилятора - это правила языка Си, который ясен и однозначен в отношении семантики равенства и операторов отношений. Я никогда не видел, чтобы компилятор ошибался.
strcmp
меньше, равно, равно или больше 0. Не гарантируется, что оно равно -1, 0 или 1, и существуют платформы, которые не возвращают эти значения, чтобы ускорить реализацию. Так что если strcmp(a, b) == TRUE
тогда, a > b
но обратное значение может не иметь места.
(1==1)
и 1
оба являются постоянными выражениями типа int
со значением 1. Они являются семантически идентичны. Я полагаю, вы можете написать код, который обслуживает читателей, которые этого не знают, но где это заканчивается?
(1 == 1)
Трюк полезен для определения TRUE
таким образом , что является прозрачным для C, но обеспечивает лучшее набрав в C ++. Тот же код можно интерпретировать как C или C ++, если вы пишете на диалекте под названием «Чистый C» (который компилируется как C или C ++) или если вы пишете заголовочные файлы API, которые могут использоваться программистами на C или C ++.
В переводных единицах C 1 == 1
имеет точно такое же значение, как 1
; и 1 == 0
имеет то же значение, что и 0
. Однако в модулях перевода C ++ 1 == 1
есть тип bool
. Таким образом, TRUE
определенный таким образом макрос лучше интегрируется в C ++.
Пример того, как он лучше интегрируется, состоит в том, что, например, если функция foo
имеет перегрузки для int
и для bool
, то foo(TRUE)
выберет bool
перегрузку. Если TRUE
это просто определено как 1
, то это не будет хорошо работать в C ++. foo(TRUE)
захочет int
перегрузку.
Конечно, C99 введены bool
, true
и , false
и они могут быть использованы в заголовочных файлах , которые работают с C99 и с C.
Тем не мение:
TRUE
и FALSE
как (0==0)
и (1==0)
предшествует C99.Если вы работаете в смешанном C и C ++ проекте, и не хотите , C99, определяет нижний регистр true
, false
а bool
вместо этого.
#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
При этом 0==0
хитрость (была?) Использовалась некоторыми программистами даже в коде, который никогда не предназначался для взаимодействия с C ++ каким-либо образом. Это ничего не значит и говорит о том, что программист неправильно понимает, как логические функции работают в C.
В случае, если объяснение C ++ не было ясным, вот тестовая программа:
#include <cstdio>
void foo(bool x)
{
std::puts("bool");
}
void foo(int x)
{
std::puts("int");
}
int main()
{
foo(1 == 1);
foo(1);
return 0;
}
Выход:
bool
int
Что касается вопроса из комментариев о том, как перегружены функции C ++, относящиеся к смешанному программированию на C и C ++. Это просто иллюстрирует разницу в типах. Действительная причина, по которой true
нужно, чтобы bool
при компиляции в C ++ была константа, - это чистая диагностика. На самых высоких уровнях предупреждения компилятор C ++ может предупредить нас о преобразовании, если мы передадим целое число в качестве bool
параметра. Одна из причин написания на чистом C заключается не только в том, что наш код более переносим (поскольку его понимают компиляторы C ++, а не только компиляторы C), но мы можем извлечь пользу из диагностических мнений компиляторов C ++.
TRUE
будут различаться в C ++.
#ifdef __cplusplus
для более ясного выражения своих намерений.
bool
и int
не имеют большого значения на практике, так как они неявно конвертируемы друг в друга (и в C фактически «одинаковы» , обратите внимание на кавычки) хотя) и не так много ситуаций, в которых вам действительно необходимо устранить неоднозначность между ними. «не так много» было, вероятно, слишком тяжело, «гораздо меньше по сравнению с кодом, использующим шаблоны и перегрузки», возможно, было бы лучше.
#define TRUE (1==1)
#define FALSE (!TRUE)
эквивалентно
#define TRUE 1
#define FALSE 0
в С.
Результатом реляционных операторов является 0
или 1
. 1==1
гарантированно будет оцениваться 1
и !(1==1)
гарантированно будет оцениваться 0
.
Нет абсолютно никаких причин использовать первую форму. Обратите внимание, что первая форма, однако, не менее эффективна, поскольку почти во всех компиляторах константное выражение оценивается во время компиляции, а не во время выполнения. Это разрешено согласно этому правилу:
(C99, 6.6p2) «Постоянное выражение может оцениваться во время перевода, а не во время выполнения, и, соответственно, может использоваться в любом месте, где может быть константа».
PC-Lint будет даже выдавать сообщение (506, постоянное значение логическое) , если вы не используете Буквальное для TRUE
и FALSE
макросов:
Для C
TRUE
должно быть определено1
. Однако в других языках используются значения, отличные от 1, поэтому некоторые программисты считают, что!0
это безопасно.
Также в C99 stdbool.h
определены определения для логических макросов true
и false
непосредственно используются литералы:
#define true 1
#define false 0
1==1
гарантированно будет оцениваться по1
if(foo == true)
, который превратится из просто плохой практики в плоскую ошибку.
(x == TRUE)
может иметь другое значение истинности, чем x
.
Помимо C ++ (уже упоминалось), еще одним преимуществом являются инструменты статического анализа. Компилятор покончит с любой неэффективностью, но статический анализатор может использовать свои собственные абстрактные типы, чтобы различать результаты сравнения и другие целочисленные типы, поэтому он неявно знает, что TRUE должен быть результатом сравнения и не должен считаться совместимым с целым числом.
Очевидно, что C говорит, что они совместимы, но вы можете запретить преднамеренное использование этой функции, чтобы помочь выявить ошибки - например, когда кто-то может запутаться &
и &&
, или они испортили свой операторский приоритет.
if (boolean_var == TRUE)
путем расширения, в if (boolean_var == (1 == 1))
которое благодаря расширенной информации о типе (1 == 1)
узла попадает шаблон if (<*> == <boolean_expr>)
.
Практическая разница - нет. 0
оценивается false
и 1
оценивается true
. Тот факт, что вы используете логическое выражение ( 1 == 1
) или 1
, для определения true
, не имеет никакого значения. Они оба получают оценку int
.
Обратите внимание , что стандартная библиотека C предоставляет специальный заголовок для определения булевых: stdbool.h
.
true
оценивается 1
и false
оценивается 0
. Си не знает о родных булевых типах, они просто целые числа.
int
со значением 0
или 1
. C действительно имеет логический тип ( _Bool
с макросом, bool
определенным в <stdbool.h>
, но он был добавлен только в C99, который не изменил семантику операторов для использования нового типа.
_Bool
и <stdbool.h>
имеет #define bool _Bool
.
1 == 1
что вас оценивают как int
. Ред.
Мы не знаем точного значения, которому равно TRUE, и компиляторы могут иметь свои собственные определения. Итак, что вы привели, так это использование внутреннего компилятора для определения. Это не всегда необходимо, если у вас есть хорошие навыки программирования, но вы можете избежать проблем из-за плохого стиля программирования, например:
if ((a> b) == ИСТИНА)
Это может быть катастрофой, если вы вручную определите TRUE как 1, а внутреннее значение TRUE - другое.
>
оператор всегда выдает 1 для истины, 0 для ложных. Нет никакой возможности того, чтобы компилятор C понял это неправильно. Сравнение равенства TRUE
и FALSE
плохой стиль; вышесказанное более четко написано как if (a > b)
. Но идея о том, что разные компиляторы C могут по-разному трактовать истину и ложь, неверна.
Обычно на языке программирования C 1 определяется как true, а 0 определяется как false. Поэтому вы часто видите следующее:
#define TRUE 1
#define FALSE 0
Однако любое число, не равное 0, будет также оценено как истинное в условном выражении. Поэтому, используя ниже:
#define TRUE (1==1)
#define FALSE (!TRUE)
Вы можете просто явно показать, что вы пытаетесь не рисковать, делая ложь равной тому, что не соответствует действительности.
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(взято с сайта coding-guidelines.com/cbook/cbook1_1.pdf 871)