"Если ([bool] == true)" требуется еще один шаг, чем "if ([bool])"?

Это чисто педантичный вопрос, чтобы выразить свое любопытство.

Я склоняюсь к последнему варианту в вопросе (так: if (boolCheck) { ... }), а коллега всегда пишет первый (if (boolCheck == true) { ... }). Я всегда его дразнил, и он всегда объяснял это как старую привычку, когда он начинал программировать.

Но мне сегодня пришло в голову, что на самом деле выписать всю часть == true может потребовать дополнительный шаг для обработки, поскольку любое выражение с оператором == оценивается по булевскому значению. Это правда?

Другими словами, как я понимаю, опция без строки == true может быть описана следующим образом:

  • Проверить X

Пока опция с, строка == true будет больше похожа:

  • Пусть Y истинно, если X истинно, иначе false
  • Проверить Y

Правильно ли я? Или, может быть, любой нормальный компилятор/интерпретатор покончит с этим различием? Или я что-то не замечаю, и на самом деле никакой разницы нет?

Очевидно, не будет никакой разницы в показателях фактической наблюдаемой работы. Как я уже сказал, мне просто интересно.

EDIT: Спасибо всем, кто опубликовал собранные результаты, чтобы проиллюстрировать, были ли разные шаги между этими двумя подходами. (Похоже, в большинстве случаев они были, хотя и незначительно.)

Я просто хочу повторить, что я не спрашивал, что такое "правильный" подход. Я понимаю, что многие люди предпочитают друг друга. Я также понимаю, что, по логике, они идентичны. Мне было просто интересно, если фактические операции, выполняемые процессором, точно такие же для обоих методов; как выясняется, большую часть времени (очевидно, это зависит от языка, компилятора и т.д.), это не так.

Ответ 1

Компилятор должен сгенерировать тот же код. Однако сравнение с истинным возможно лучше, потому что оно более явное. Обычно я не делаю явного сравнения, но вы не должны высмеивать его за это.

Изменить: Самый простой способ сказать - попробовать. Компилятор MS (cl.exe) генерирует одинаковое количество шагов в сборке:

int _tmain(int argc, _TCHAR* argv[])
{
    bool test_me = true;

    if (test_me) {
004113C2  movzx       eax,byte ptr [test_me] 
004113C6  test        eax,eax 
004113C8  je          wmain+41h (4113E1h) 
        printf("test_me was true!");
    }

    if (test_me == true) {
004113E1  movzx       eax,byte ptr [test_me] 
004113E5  cmp         eax,1 
004113E8  jne         wmain+61h (411401h) 
        printf("still true!");
    }
    return 0;
}

На данный момент вопрос заключается в том, что тест и cmp имеют одинаковую стоимость? Я думаю, что да, хотя эксперты могут указывать на различия.

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

Ответ 2

Я бы ожидал, что разница будет оптимизирована любым полуподобным компилятором.

(Я только что проверил с С#, и скомпилированный код для обоих синтаксисов точно такой же.)

Ответ 3

Я думаю, что сравнение с истиной показывает отсутствие понимания вашим партнером. Bools следует назвать вещами, чтобы избежать этого (например, isAvaliable: if (isAvailable) {...}).

Ответ 4

Дублирующий вопрос (Должен ли я использовать`! IsGood` или `IsGood == false`?). Здесь указатель на мой предыдущий ответ:

Методика тестирования конкретно против истины или ложных - это плохая практика если переменная, о которой идет речь, действительно предполагается использовать в качестве логического значения (даже если его тип не является логическим) - особенно в C/С++. Тестирование против true может (и, вероятно, будет) привести к тонкие ошибки.

Подробнее см. следующий ответ SO:

Должен ли я использовать`! IsGood` или `IsGood == false`?

Вот поток, в котором подробно объясняется, почему "== true" часто является ложным более подробно, включая объяснение Страуструпа: https://qt-project.org/forums/viewthread/32642

Ответ 5

Здесь разбор Python (2.6):

>>> def check(x): return (bool(x) == True)

>>> import dis
>>> dis.dis(check)
  1           0 LOAD_GLOBAL              0 (bool)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 LOAD_GLOBAL              1 (True)
             12 COMPARE_OP               2 (==)
             15 RETURN_VALUE        
>>> def check2(x): return bool(x)

>>> dis.dis(check2)
  1           0 LOAD_GLOBAL              0 (bool)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE        

Я полагаю, что причина check не оптимизирована из-за того, что Python является динамическим языком. Это само по себе не означает, что Python использует плохой компилятор, но он может стоить сделать небольшой вывод типа здесь. Может быть, это имеет значение, когда создается файл .pyd?

Ответ 6

По моему опыту if (flag==true) - плохая практика.

Первый аргумент академический:

Если у вас есть bool flag, это либо true, либо false.

Теперь выражение

(flag==true)

снова, true или false - он не является более выразительным, только избыточным - flag не может получить "более правдивый" или "более ложный", чем он уже есть. Это было бы "яснее", только если это не очевидно. flag является логическим, но существует стандартный способ исправить то, что работает для всех типов: выберите лучшее имя.

Растяжение этого без причины, следующее было бы "еще лучше":

((flag==true)==true)

Второй аргумент является прагматичным и специфичным для платформы

C и ранние версии С++ не имели реального типа "bool", поэтому существуют различные соглашения для флагов, наиболее распространенным из которых является то, что отличное от нуля истинно. Нередко API возвращает тип BOOL на основе целочисленного числа, но не обеспечивает, чтобы возвращаемое значение равно 0 или 1.

В некоторых средах используются следующие определения:

#define FALSE 0
#define TRUE (!FALSE)

удачи с if ((1==1) == TRUE)

Кроме того, некоторые платформы используют разные значения - например, VARIANT_BOOL для VB interop - это short, а VARIANT_TRUE - -1.

При смешивании библиотек, использующих эти определения, явное сравнение с истинным может легко быть ошибкой, замаскированной под хорошие намерения. Итак, не надо.

Ответ 7

Компилятор MSVС++ 6.0 генерирует несколько другой код для двух форм:

4:        if ( ok ) {
00401033   mov         eax,dword ptr [ebp-8]
00401036   and         eax,0FFh
0040103B   test        eax,eax
0040103D   je          main+36h (00401046)
....
7:        if ( ok == true ) {
00401046   mov         ecx,dword ptr [ebp-8]
00401049   and         ecx,0FFh
0040104F   cmp         ecx,1
00401052   jne         main+4Bh (0040105b)

Бывшая версия должна быть очень немного быстрее, если я правильно помню свои 8086 таймингов: -)

Ответ 8

Это попадает на определенные языки и что они считают "правдивыми" значениями. Здесь два общих: JavaScript и PHP.

Тройка равна оператору на обоих этих языках, гарантирует, что вы действительно проверяете логический тип истины. Например, проверка PHP на if ($value) может отличаться от if ($value==true) или if ($value===true):

$f = true;
$z = 1;
$n = null;
$a = array(1,2);

print ($f)        ?'true':'false'; // true
print ($f==true)  ?'true':'false'; // true
print ($f===true) ?'true':'false'; // true
print "\n";
print ($z)        ?'true':'false'; // true
print ($z==true)  ?'true':'false'; // true
print ($z===true) ?'true':'false'; // false
print "\n";
print ($n)        ?'true':'false'; // false
print ($n==true)  ?'true':'false'; // false
print ($n===true) ?'true':'false'; // false
print "\n";
print ($a)        ?'true':'false'; // true
print ($a==true)  ?'true':'false'; // true
print ($a===true) ?'true':'false'; // false
print "\n";
print "\n";

Я ожидаю, что языки, которые каждый говорит ежедневно, будут сообщать, как один из них рассматривает этот вопрос.

Ответ 9

В синтаксисе "boolCheck == true" может быть некоторое обоснование, зависящее от имени тестируемой переменной.

Например, если имя переменной было "state", вы можете либо:

if (state) {
   ...
}

или вы можете иметь

if (state == true) {
   ...
}

В этом случае, я думаю, последняя форма более ясна и очевидна.

Другим примером может быть переменная типа "enabled", в этом случае первая форма становится более понятной.

Теперь наличие логической переменной, называемой "состояние", является плохой практикой, но вы можете не иметь никакого контроля над этим, и в этом случае синтаксис "== true" может улучшить читаемость кода.

Ответ 10

Это зависит от компилятора. Могут быть оптимизации для обоих случаев.

Ответ 11

Тестирование равенства с истинным может привести к ошибке, по крайней мере в C: в C, если "можно использовать для целочисленных типов (а не только для логических типов)) и принимать любое ненулевое значение; однако символ" ИСТИНА" является одним конкретным ненулевым значением (например, 1). Это может стать важным с битовыми флагами:

if (flags & DCDBIT)
{
    //do something when the DCDBIT bit is set in the flags variable
}

Итак, задана такая функция...

int isDcdSet()
{
    return (flags & DCDBIT);
}

... выражение "if (isDcdSet())" не совпадает с "if (isDcdSet() == TRUE)".

В любом случае; Я бы подумал, что оптимизирующий компилятор должен оптимизировать любую разницу (потому что нет логической разницы), предполагая, что это язык с истинным булевым (не только целочисленным) типом.

Ответ 12

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

ifstream fin;
...
if( ! fin)
...

Ответ 13

Возможно, это не так, если вы работаете с nullable bool.

Пример:

Bool? myBool = true

if(myBool)  // This will not compile

if(myBool == true)  //this will compile

Ответ 14

ИМХО это плохая идея использовать форму if (boolCheck == true) по простой причине: если вы случайно наберете один знак "равно" вместо двойного (т.е. if (boolCheck = true)), он назначит true на boolCheck и всегда будет возвращать true, что, очевидно, будет ошибкой. Конечно, большинство современных компиляторов покажут предупреждение, увидев, что (по крайней мере, компилятор С#), но многие разработчики просто игнорируют предупреждения...

Если вы хотите быть явным, вы должны предпочесть эту форму: if (true == boolCheck). Это позволит избежать случайного присвоения переменной и вызовет ошибку компиляции, если вы забудете знак "равно".