/*
** Bit set, clear, and test operations
**
** public domain snippet by Bob Stout
*/
typedef enum {ERROR = -1, FALSE, TRUE} LOGICAL;
#define BOOL(x) (!(!(x)))
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
ОК, давайте разберемся ...
Общее выражение, с которым у вас, похоже, возникают проблемы во всех этих случаях, это "(1L << (posn))". Все это создает маску с одним битом на
и который будет работать с любым целочисленным типом. Аргумент "posn" указывает
положение, где вы хотите немного. Если posn == 0, то это выражение будет
оценить: </p>
0000 0000 0000 0000 0000 0000 0000 0001 binary.
Если posn == 8, это будет равно
0000 0000 0000 0000 0000 0001 0000 0000 binary.
Другими словами, он просто создает поле из 0 с 1 в указанном
позиция. Единственная сложная часть в макросе BitClr (), где нам нужно установить
один бит 0 в поле 1. Это достигается с помощью 1
дополнение того же выражения, которое обозначено оператором тильда (~).
Как только маска создана, она применяется к аргументу, как вы предлагаете,
с помощью побитовых и (&), или (|), и xor (^) операторов. С маской
имеет тип long, макросы будут работать так же хорошо на char, short, int,
или длинные.
Суть в том, что это общее решение для всего класса
проблемы. Конечно, возможно и даже уместно переписать
эквивалент любого из этих макросов с явными значениями маски каждый раз, когда вы
нужен, но зачем это делать? Помните, что подстановка макросов происходит в
препроцессор и поэтому сгенерированный код будет отражать тот факт, что значения
компилятором считаются постоянными, т. е. его использование также эффективно
обобщенные макросы, чтобы «изобретать велосипед» каждый раз, когда вам нужно сделать
немного манипуляций.
убежденный? Вот некоторый тестовый код - я использовал Watcom C с полной оптимизацией
и без использования _cdecl, чтобы результирующая разборка была бы такой же чистой, как
возможно:
---- [TEST.C] -------------------------------------- --------------------------
#define BOOL(x) (!(!(x)))
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitTst(arg,posn) BOOL((arg) & (1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
int bitmanip(int word)
{
word = BitSet(word, 2);
word = BitSet(word, 7);
word = BitClr(word, 3);
word = BitFlp(word, 9);
return word;
}
---- [TEST.OUT (разобрано)] ----------------------------------- ------------
Module: C:\BINK\tst.c
Group: 'DGROUP' CONST,CONST2,_DATA,_BSS
Segment: _TEXT BYTE 00000008 bytes
0000 0c 84 bitmanip_ or al,84H ; set bits 2 and 7
0002 80 f4 02 xor ah,02H ; flip bit 9 of EAX (bit 1 of AH)
0005 24 f7 and al,0f7H
0007 c3 ret
No disassembly errors
---- [finis] ---------------------------------------- -------------------------