Если вы действительно хотите предикат "строго положительный" для int n
без использования условных выражений (при условии дополнения до 2):
-n
будет иметь бит знака (верхний), если n
был строго положительным, и сбрасывается во всех других случаях , за исключением n == INT_MIN
;
~n
будет иметь установленный бит знака, если n
был строго положительным, или 0, и очищаться во всех других случаях , включая n == INT_MIN
;
- ... поэтому
-n & ~n
будет иметь установленный бит знака, если n было строго положительным, и очищаться во всех других случаях.
Примените беззнаковое смещение, чтобы превратить это в ответ 0/1:
int strictly_positive = (unsigned)(-n & ~n) >> ((sizeof(int) * CHAR_BIT) - 1);
РЕДАКТИРОВАТЬ: как указано в комментариях caf, -n
вызывает переполнение, когда n == INT_MIN
(все еще предполагается, что дополнение 2). Стандарт C позволяет программе в этом случае не работать (например, вы можете включить прерывания для переполнения со знаком, используя GCC с опцией -ftrapv
). Приведение n
к беззнаковому исправляет проблему (арифметика без знака не вызывает переполнения). Таким образом, улучшение будет:
unsigned u = (unsigned)n;
int strictly_positive = (-u & ~u) >> ((sizeof(int) * CHAR_BIT) - 1);