Зачем использовать!!(условие) вместо (условие)?

Я видел код, где люди использовали условные предложения с двумя '!'

#define check_bit(var, pos)       (!!((var) & (1 << (pos))))
#define likely(x)       __builtin_expect(!!(x),1)
#define unlikely(x)     __builtin_expect(!!(x),0)

Вот некоторые примеры, которые я смог найти.

Есть ли преимущество в использовании !!(condition) над (condition)?

4 ответа

Решение

Хорошо, если переменная, которую вы применяете !! это уже не 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).

Для справки в С99 bool макрос расширяется до _Bool, true расширяется до 1 а также false расширяется до 0, Подробности приведены в разделе проекта стандарта 7.16 Логический тип и значения.

Логическое отрицание кроется в 6.5.3.3 Унарные арифметические операторы в пункте 5:

Результат оператора логического отрицания! равен 0, если значение его операнда сравнивается с 0, 1, если значение его операнда сравнивается равным 0. Результат имеет тип int. Выражение!E эквивалентно (0==E).

Одинарный ! Оператор логического отрицания, примененный к любому скаляру, дает int значение 0 если его операнд не равен нулю, 1 если операнд равен нулю. Цитируя стандарт:

Выражение !E эквивалентно (0==E),

применение ! дважды к одному и тому же скалярному значению выдает результат, который равен false, если значение равно false, true, если значение равно true, но результат нормализуется до 0 или же 1соответственно.

В большинстве случаев в этом нет необходимости, поскольку любое скалярное значение можно использовать непосредственно как условие. Но в некоторых случаях вам действительно нужно 0 или же 1 значение.

В C99 или позже, приведение выражения к _Bool (или для bool если у вас есть #include <stdbool.h> ведет себя аналогично и может считаться более понятным. Но (а) результат имеет тип _Bool скорее, чем intи (b) если вы используете компилятор до C99, который не поддерживает _Bool и вы определили свой bool типа, он не будет вести себя так же, как С99 _Bool,

Самое большое, что я могу видеть, это то, что это заставит (или нормализует) значение в 1 или же 0 (это логическое значение) независимо от того, как x или же var выражение расширяется (например, char или же double или же int или т. д.).

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

Другие вопросы по тегам