Я видел определения в C
#define TRUE (1==1)
#define FALSE (!TRUE)
Это необходимо? В чем преимущество простого определения TRUE как 1 и FALSE как 0?
Я видел определения в C
#define TRUE (1==1)
#define FALSE (!TRUE)
Это необходимо? В чем преимущество простого определения TRUE как 1 и FALSE как 0?
Этот подход будет использовать фактический тип boolean
(и разрешать в true
и false
), если компилятор его поддерживает. (в частности, С++)
Однако было бы лучше проверить, используется ли C++ (с помощью макроса __cplusplus
), и действительно использовать true
и false
.
В компиляторе C это эквивалентно 0
и 1
.
(обратите внимание, что удаление круглых скобок нарушит это из-за порядка операций)
1==1
является int
. (см. stackoverflow.com/questions /7687403/ .)
- person Mat; 09.06.2013
boolean
?
- person SLaks; 09.06.2013
true
или false
.
- person Mat; 09.06.2013
#define TRUE true
и #define FALSE false
всякий раз, когда определяется __cplusplus
.
- person Nikos C.; 09.06.2013
#define TRUE (!0) #define FALSE (!TRUE)
- person Ayxan Haqverdili; 29.08.2020
Ответ — переносимость. Числовые значения TRUE
и FALSE
не важны. Что важно, так это то, что оператор типа if (1 < 2)
оценивается как if (TRUE)
, а оператор типа if (1 > 2)
оценивается как if (FALSE)
.
Конечно, в C (1 < 2)
оценивается как 1
, а (1 > 2)
оценивается как 0
, поэтому, как говорили другие, с точки зрения компилятора нет никакой практической разницы. Но позволяя компилятору определять TRUE
и FALSE
в соответствии с его собственными правилами, вы делаете их значения явными для программистов и гарантируете согласованность в вашей программе и любой другой библиотеке (при условии, что другая библиотека соответствует стандартам C... вы был бы поражен).
Немного истории
Некоторые BASIC определяют FALSE
как 0
, а TRUE
как -1
. Как и многие современные языки, они интерпретировали любое ненулевое значение как TRUE
, но оценивали логические выражения, которые были истинными, как -1
. Их операция NOT
была реализована путем добавления 1 и перестановки знака, потому что это было эффективно. Таким образом, «НЕ x» стало -(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()
равно
0, если yourString == myString
‹0, если yourString < myString
>0, если yourString > myString
Таким образом, строка выше возвращает TRUE
только тогда, когда yourString > myString
.
Правильный способ сделать это либо
// Valid, but still treats int as bool.
if (strcmp(yourString, myString))
or
// 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
. Собственные правила компилятора — это правила языка C, которые ясно и недвусмысленно относятся к семантике равенства и операций отношения. Я никогда не видел, чтобы компилятор ошибался в этом.
- person Keith Thompson; 10.06.2013
strcmp
, меньше, равно или больше 0. Не гарантируется, что оно будет -1, 0 или 1, и в дикой природе есть платформы, которые не возвращают эти значения для ускорения реализации. . Итак, если strcmp(a, b) == TRUE
, то a > b
, но обратное значение может быть неверным.
- person Maciej Piechotka; 10.06.2013
(1==1)
и 1
являются константными выражениями типа int
со значением 1. Они семантически идентичны. Я полагаю, что вы можете написать код, рассчитанный на читателей, которые этого не знают, но где он заканчивается?
- person Keith Thompson; 10.06.2013
TRUE
, безусловно, важно. Это важная часть булевой алгебры, которая определяет ее таким образом, чтобы поддерживать правильное соответствие. между булевыми операциями и целочисленными.
- person jthill; 10.06.2013
Трюк с (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++.
- person user4815162342; 10.06.2013
#ifdef __cplusplus
, чтобы выразить свое намерение гораздо больше. четко.
- person Keith Thompson; 10.06.2013
bool
и int
, не имеют большого значения на практике, поскольку они неявно конвертируются друг в друга (и в C на самом деле то же самое, обратите внимание на кавычки), и не так много ситуаций, в которых вам действительно нужно устранить неоднозначность между ними. не много было, вероятно, слишком тяжелым, намного меньше по сравнению с кодом, использующим шаблоны и перегрузку, возможно, было бы лучше.
- person Christian Rau; 10.06.2013
(0==0)
как подходящий способ определить TRUE
, не зависящий от языка, и я согласен что блок #ifdef __cplusplus
намного понятнее. Но тем не менее этот макрос - способ сделать это, пусть и не самый лучший. Единственное, что вызвало мой комментарий, это то, что вы прыгнули на пример с перегруженными функциями, тогда как это было просто примером более внутренней и концептуальной проблемы, необходимости правильного ввода (что вы, как предполагает ваш предыдущий комментарий, также высоко цените) .
- person Christian Rau; 10.06.2013
#define TRUE (1==1)
#define FALSE (!TRUE)
эквивалентно
#define TRUE 1
#define FALSE 0
in C.
Результатом операторов отношения является 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
вместо неопределенного ненулевого значения?
- person djechlin; 09.06.2013
1==1
гарантированно будет оцениваться как 1
- person ouah; 09.06.2013
false
требуется иметь конкретное значение, а именно 0, то почему не принято определять false
как 0
, а true
как (!0)
?
- person Nikos C.; 09.06.2013
if(foo == true)
, который превратится из просто плохой практики в откровенно глючную.
- person djechlin; 09.06.2013
(!0)
является 1
по определению оператора !
.
- person Keith Thompson; 09.06.2013
(x == TRUE)
может иметь другое значение истины, чем x
.
- person Joshua Taylor; 09.06.2013
Помимо C++ (уже упомянутого), еще одним преимуществом являются инструменты статического анализа. Компилятор избавится от любой неэффективности, но статический анализатор может использовать свои собственные абстрактные типы, чтобы отличать результаты сравнения от других целочисленных типов, поэтому он неявно знает, что TRUE должен быть результатом сравнения и не должен считаться совместимым. с целым числом.
Очевидно, что C говорит, что они совместимы, но вы можете запретить преднамеренное использование этой функции, чтобы помочь выявить ошибки — например, когда кто-то мог перепутать &
и &&
, или они напортачили со своим приоритетом оператора.
if (boolean_var == TRUE)
путем расширения до if (boolean_var == (1 == 1))
, который благодаря расширенной информации о типе узла (1 == 1)
попадает в шаблон if (<*> == <boolean_expr>)
.
- person Kaz; 09.06.2013
Практической разницы нет. 0
оценивается как false
, а 1
оценивается как true
. Тот факт, что вы используете логическое выражение (1 == 1
) или 1
для определения true
, не имеет значения. Они оба оцениваются как int
.
Обратите внимание, что стандартная библиотека C предоставляет специальный заголовок для определения логических значений: stdbool.h
.
true
оценивается как 1
, а false
оценивается как 0
. C не знает о нативных логических типах, это просто целые числа.
- person djechlin; 09.06.2013
int
со значением 0
или 1
. C действительно имеет логический тип (_Bool
, с макросом bool
, определенным в <stdbool.h>
, но он был добавлен только в C99, который не изменил семантику операторов для использования нового типа.
- person Keith Thompson; 09.06.2013
_Bool
, а <stdbool.h>
имеет #define bool _Bool
.
- person Keith Thompson; 09.06.2013
1 == 1
оценивается как int
. Отредактировано.
- person Shoe; 09.06.2013
Мы не знаем точного значения, которому равно TRUE, и компиляторы могут иметь свои собственные определения. Итак, вы используете внутреннюю компилятора для определения. Это не всегда необходимо, если у вас есть хорошие привычки программирования, но вы можете избежать проблем из-за плохого стиля кодирования, например:
если ((а > б) == ИСТИНА)
Это может быть катастрофой, если вы вручную определите TRUE как 1, в то время как внутреннее значение TRUE будет другим.
>
всегда возвращает 1 для истинного значения и 0 для ложного. Нет никакой возможности, чтобы какой-либо компилятор C ошибся. Сравнения на равенство с TRUE
и FALSE
неуместны; выше более четко написано как if (a > b)
. Но идея о том, что разные компиляторы C могут по-разному обрабатывать истину и ложь, просто неверна.
- person Keith Thompson; 15.10.2013
Обычно в языке программирования C 1 определяется как истина, а 0 определяется как ложь. Поэтому вы довольно часто видите следующее:
#define TRUE 1
#define FALSE 0
Однако любое число, не равное 0, также будет оцениваться как истинное в условном выражении. Поэтому, используя следующее:
#define TRUE (1==1)
#define FALSE (!TRUE)
Вы можете просто явно показать, что пытаетесь перестраховаться, приравняв false к тому, что не соответствует действительности.
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(взято со страницы coding-guidelines.com/cbook/cbook1_1.pdf 871) - person osgx   schedule 09.06.2013