Вы не реализуете логические элементы только потому, что они имеют функциональную полноту, особенно если другие логические элементы изначально доступны. Вы реализуете то, что чаще всего используется компиляторами.
NAND, NOR и XNOR очень редко нужны. Помимо классических побитовых операторов AND, OR и XOR, только ANDN ( ~a & b
) - который не является NAND ( ~(a & b)
) - будет иметь практическую полезность. Если таковые имеются, ЦП должен реализовать это (и действительно, некоторые ЦП действительно реализуют ANDN).
Для объяснения практической полезности ANDN представьте, что у вас есть битовая маска, которая использует много битов, но вас интересуют только некоторые из них, а именно:
enum my_flags {
IT_IS_FRIDAY = 1,
...
IT_IS_WARM = 8,
...
THE_SUN_SHINES = 64,
...
};
Обычно вы хотите проверить свои биты в битовой маске
- Они все установлены
- Хотя бы один установлен
- По крайней мере, один не установлен
- Ни один не установлен
Давайте начнем с того, что соберем ваши биты интереса:
#define BITS_OF_INTEREST (IT_IS_FRIDAY | IT_IS_WARM | THE_SUN_SHINES)
1. Все интересующие вас биты установлены: побитовое ANDN + логическое NOT
Допустим, вы хотите знать, все ли ваши биты интересов установлены. Вы можете видеть это как (my_bitmask & IT_IS_FRIDAY) && (my_bitmask & IT_IS_WARM) && (my_bitmask & THE_SUN_SHINES)
. Однако, как правило, вы свернули бы это в
unsigned int life_is_beautiful = !(~my_bitmask & BITS_OF_INTEREST);
2. Установлен хотя бы один интересующий бит: побитовое И
Теперь давайте скажем, что вы хотите знать, установлен ли хотя бы один интерес. Вы можете видеть это как (my_bitmask & IT_IS_FRIDAY) || (my_bitmask & IT_IS_WARM) || (my_bitmask & THE_SUN_SHINES)
. Однако, как правило, вы свернули бы это в
unsigned int life_is_not_bad = my_bitmask & BITS_OF_INTEREST;
3. По крайней мере , один бит интереса не установлен: побитовое ANDN
Теперь предположим, что вы хотите знать, если хотя бы один бит интереса не установлен. Вы можете видеть это как !(my_bitmask & IT_IS_FRIDAY) || !(my_bitmask & IT_IS_WARM) || !(my_bitmask & THE_SUN_SHINES)
. Однако, как правило, вы свернули бы это в
unsigned int life_is_imperfect = ~my_bitmask & BITS_OF_INTEREST;
4. Бит интереса не установлен: побитовое И + логическое НЕ
Теперь предположим, что вы хотите знать, не установлены ли все интересующие вас биты . Вы можете видеть это как !(my_bitmask & IT_IS_FRIDAY) && !(my_bitmask & IT_IS_WARM) && !(my_bitmask & THE_SUN_SHINES)
. Однако, как правило, вы свернули бы это в
unsigned int life_is_horrible = !(my_bitmask & BITS_OF_INTEREST);
Это обычные операции, выполняемые над битовой маской, плюс классическое побитовое ИЛИ и XOR. Я думаю , однако , что язык (который не является центральным процессором ) должен включать в себя побитовое NAND, NOR и операторы XNOR (символы которых были бы ~&
, ~|
а ~^
), несмотря на редко. Я бы не стал включать оператор ANDN в язык, так как он не коммутативный ( a ANDN b
не то же самое, что b ANDN a
) - лучше писать ~a & b
вместо a ANDN b
, первый показывает более четко асимметрию операции.