Зачем использовать (условие) вместо (условие)?
Я видел код, в котором люди использовали условные предложения с двумя "!"
#define check_bit(var, pos) (!!((var) & (1 << (pos))))
#define likely(x) __builtin_expect(!!(x),1)
#define unlikely(x) __builtin_expect(!!(x),0)
- некоторые из примеров, которые я мог найти.
Есть ли преимущество в использовании !!(condition)
над (condition)
?
Ответы
Ответ 1
Хорошо, если переменная, которую вы применяете !!
, уже не является bool
(ноль или один), тогда она нормализует значение как на 0
, так и на 1
.
В отношении __builtin_expect
этот поток новичков ядра обсуждает нотацию, и один из ответов объясняет (акцент мой):
Подпись __builtin_expect
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html):
long __builtin_expect (long exp, long c)
Обратите внимание, что параметр exp должен быть интегральным выражением, поэтому никакие указатели или типа с плавающей запятой. двойное отрицание обрабатывает преобразование из эти типы для встроенных выражений автоматически. Таким образом, вы можете просто пишите: скорее всего (ptr) вместо вероятного (ptr!= NULL).
Для справки в C99 bool
макрос расширяется до _Bool
, true
расширяется до 1
и false
расширяется до 0
. Подробности приведены в проекте стандартного раздела 7.16
Логический тип и значения.
Логическое отрицание рассматривается в 6.5.3.3
Унарных арифметических операторах в параграфе 5:
Результат оператора логического отрицания! 0, если значение его операнда сравнивается не равно 0, 1, если значение его операнда сравнивается с равным 0. Результат имеет тип int. Выражение! E эквивалентно (0 == E).
Ответ 2
Унарный оператор !
логического отрицания, применяемый к любому скаляру, дает значение int
0
, если его операнд отличен от нуля, 1
, если операнд равен нулю. Цитирование стандарта:
Выражение !E
эквивалентно (0==E)
.
Применяя !
дважды к одному и тому же скалярному значению, получаем результат, если false, если значение ложно, true, если значение истинно, но результат нормализуется до 0
или 1
соответственно.
В большинстве случаев это необязательно, так как любое скалярное значение может использоваться непосредственно как условие. Но в некоторых случаях вам действительно нужно значение 0
или 1
.
В C99 или более поздней версии выражение _Bool
(или bool
), если у вас есть #include <stdbool.h>
, ведет себя аналогично и может считаться более ясным. Но (a) результат имеет тип _Bool
, а не int
и (b) если вы используете компилятор pre-C99, который не поддерживает _Bool
, и вы определили свой собственный тип bool
, он не будет вести себя так же, как C99 _Bool
.
Ответ 3
Самый большой, что я вижу, заключается в том, что он будет принудительно (или нормализовать) значение в 1
или 0
(это логическое значение) независимо от того, как выражение x
или var
расширяется (например, char
или double
или int
или т.д.).
Ответ 4
Он ссылается на логическое значение, которое иногда может быть полезно.