Пишет ли логические условия «полностью»? скомпрометировать производительность?

Для удобства чтения я люблю писать булевы условия «полностью» на C / C ++, например:

if (foo == true) вместо if (foo) а также if (foo == false) вместо if (!foo),

Влияет ли это на производительность?

1

Решение

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

Используя gcc 4.1.2 на SLES 10, я получаю немного другой машинный код для if ( foo == false ) против if ( !foo ); учитывая следующий исходный код:

if ( foo == false )
{
printf( "foo is false\n" );
}

if ( !foo )
{
printf( "foo is 0\n" );
}

Я получаю следующий машинный код (gcc -S -std=c99 -pedantic -Wall -Werror):

        movb    $0, -1(%rbp)      ;; foo = false
cmpb    $0, -1(%rbp)      ;; if ( foo == false )
jne     .L6               ;; {
movl    $.LC2, %edi       ;;
call    puts              ;;    printf( "foo is false\n" );
.L6:                              ;; }
movzbl  -1(%rbp), %eax    ;; if ( !foo )
xorl    $1, %eax
testb   %al, %al
je      .L8               ;; {
movl    $.LC3, %edi       ;;
call    puts              ;;    printf( "foo is 0\n" );
.L8:                              ;; }
movl    $0, %eax

Для этой конкретной платформы, компилятора, кода и набора опций компилятора, if (!foo) может оказаться немного медленнее, чем if ( foo == false )1.

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

Код для читабельности первый; if ( foo ) а также if ( !foo ) формы, как правило, идиоматичны для простых булевых тестов, и именно этого ожидают увидеть большинство программистов на C и C ++. Сказав это, здесь нет ничего плохого в написании if ( foo == TRUE ) а также if ( foo == FALSE ) если вы чувствуете, что он лучше передает смысл кода (или если вы решили определить TRUE как 0 и FALSE как 1 по любой причине).

Но не принять это решение на основе производительности если:

  1. Вы не соответствуете жестким требованиям к производительности;
  2. Вы оптимизировали свой алгоритм и структуры данных соответственно; а также
  3. Профилирование шоу это конкретное утверждение это остающееся узкое место.

1. Или нет; это зависит от того, сколько циклов xorl а также testb требовать против cmpb и насколько быстрее это зарегистрироваться %eax непосредственно, чем вычислять -1(%rbp) и получить доступ к полученному местоположению; Насколько я знаю, это мытье.

2

Другие решения

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

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

3

if(foo == true)

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

if( ! foo)

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

Если вы допустите злонамеренную перегрузку, все ставки в любом случае будут отменены, и вы получите ту проблему, которую ожидаете.

Тем не менее, вышеупомянутое не является каноническим примером для глупости всегда добавлять явное сравнение.
Это было бы:

if(foo)
if(foo == true)
if((foo == true) == true)
// ...

Недостатки:

  • Ненужное многословие, ничего не разъясняющее.
  • Опасность забыть =и так, пытаясь присвоить значение.
  • Сколько «уточнения» будет достаточно ясно?
  • Если не использовать ключевые слова для логических констант, но лежат в основе 0 и 1, выполнение этого риска сопряжено с риском равенства на 1, где необходимо неравенство с 0.

Имейте в виду, что в C, C ++ и некоторых родственных языках то же самое относится и к указателям, целым числам (включая символьные типы) и большинству пользовательских типов.

1

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

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

-4
По вопросам рекламы [email protected]