Я довольно рад, что в C вещами как это является плохой код:
(var_a == var_b) ? TRUE : FALSE
Однако что является лучшим способом иметь дело с этим:
/* Header stuff */
#define INTERESTING_FLAG 0x80000000
typedef short int BOOL;
void func(BOOL);
/* Code */
int main(int argc, char *argv[])
{
unsigned long int flags = 0x00000000;
... /* Various bits of flag processing */
func(flags & INTERESTING_FLAG); /* func never receives a non-zero value
* as the top bits are cut off when the
* argument is cast down to a short
* int
*/
}
Действительно ли это приемлемо (для любого значения приемлемых, которые Вы используете) иметь (flags & FLAG_CONST) ? TRUE : FALSE
?
Я бы предпочел (флаги и const_flag)! = 0
. Все еще лучше, используйте тип _bool, если у вас есть (хотя он часто замаскирован как Bool
).
Установите флаги компилятора максимально насколько это возможно, чтобы предупредить вас о любом предложении, который теряет биты и лечить предупреждения в качестве ошибок.
Некоторые люди не нравятся, но я использую !!
IE
!!(flags & CONST_FLAG)
(не как макрос TO_BOOL как кто-то еще предложен, просто прямо в коде).
Если его использовали больше людей, он не был бы замечен как необычный , поэтому начните использовать его !!
Возможно, это не очень популярное решение, но иногда бывает полезно использовать макросы.
#define to_bool(x) (!!(x))
Теперь мы можем безопасно иметь все, что захотим, не опасаясь переполнения нашего типа:
func(to_bool(flags & INTERESTING_FLAG));
Другой альтернативой может быть определение вашего булевого типа как intmax_t
(из stdint.h
), так что невозможно усечь значение до фальшивости.
Пока я здесь, я хочу сказать, что вы должны использовать typedef
для определения нового типа, а не #define
:
typedef short Bool; // or whatever type you end up choosing
Некоторые могут возразить, что вы должны использовать переменную const
вместо макроса для числовых констант:
const INTERESTING_FLAG = 0x80000000;
В целом, есть вещи и получше, на которые вы можете потратить свое время. Но макросы для typedef
s немного глупые.
Вы можете избежать этого пары разных способов:
во-первых.
void func(unsigned long int);
позаботится об этом ...
или
if(flags & INTERESTING_FLAG)
{
func(true);
}
else
{
func(false);
}
также сделает это.
Редактировать: (Флаги и интересные_flag)! = 0
также хорошо. Наверное лучше.
Это частично выключено в тему:
Я также создал функцию справки, которая делает его очевидным для читателя, какова цель чека, так что вы не заполняете свой код Этот явный флаг проверять повсюду. Типичный тип флаг облегчит изменять тип и реализацию флага позже.
Современные компиляторы поддерживают ключевое слово Inline, которое может избавиться от накладных расходов производительности в вызове функций.
typedef unsigned long int flagtype;
...
inline bool hasInterestingFlag(flagtype flags) {
return ((flags & INTERESTING_FLAG) != 0);
}
Вот почему вы должны использовать значения только в «логическом» пути, когда эти значения имеют явную булевую семантику. Ваша стоимость не удовлетворяет правилу TAHT, поскольку он имеет выраженную целочисленную семантику (или, точнее, семантику битовой массивы). Чтобы преобразовать такое значение для логика, сравните его с 0
func((flags & INTERESTING_FLAG) != 0);
Я бы в любом случае вызвала func с (flags & INTERESTING_FLAG) != 0
в качестве аргумента для указания, что необходим булевый параметр, а не арифметический результат flags & INTERESTING_FLAG
.
У вас есть что-нибудь против
flags & INTERESTING_FLAG ? TRUE : FALSE
?