C bit of macros, can someone explain to me how this works?

I am trying to implement an erathostenes sieve for a school project, and I decided to do this using bit arrays. While I was looking for materials, I came across these three macros, they work flawlessly, but I can not read (understand) them.

#define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0) #define SETBIT(x,i) x[i>>3]|=(1<<(i&7)); #define CLEARBIT(x,i) x[i>>3]&=(1<<(i&7))^0xFF; 

Could you explain at least one of them to me in detail, I have very simple knowledge about bitwise operations in C (basically I know that they exist).

Will this work work on a different architecture using different concepts? Thanks in advance.

+4
source share
3 answers

First, these macros assume that CHAR_BIT == 8 and i >> 3 are actually i / 8 . (So ​​really this code should say i / CHAR_BIT .) This first expression evaluates the byte that contains your desired bit, and therefore is the index of the array in your x array (which should be an unsigned char array!).

Now that we have selected the correct byte, namely x[i >> 3] (or x[i / CHAR_BIT] in your own, better code), we need to perform bit-driving. Again, i & 7 really wants to be i % CHAR_BIT , and it only extracts the rest of your bit counter, which gives an offset in byte.

Example. Requesting the 44th bit with i = 43 and assuming CHAR_BIT = 8 , i / CHAR_BIT is 5, so we are in the sixth byte, and i % CHAR_BIT is 3, so we look at the fourth bit of the sixth byte.

Actual bit management is common; for example, testing for a given bit performs the bit-mut And with the corresponding bit pattern (namely 1 << k for the k th bit); setting a bit uses a bit-wise OR, and zeroing requires something a little more (think about it!).

+4
source

x is an array of characters. i is the bit index. since each char is 8 bits, the last 3 bits of i determine the bit in char, and the remaining bits define char in the array.

i>>3 shift i 3 bits to the right, so you get the part that tells you that char, so x[i>>3] is a char that contains the bit indexed i .

i&7 is the last 3 bits of i (since 7 10 ==111 2 ), so this is the bit index in char. 1<<(i&7) is a char (this is truly an int, but in this context you can ignore the difference), which has a bit indexed by i on and the rest of the bits are off. (mask bit)

char&mask is a common way to check if a bit is enabled.

char|=mask is the usual way to enable bits.

char&=~mask is the usual way to disable the bit, and if mask is char, then ~mask==mask^0xFF .

I do not think these macros are endiannes dependent. (if you got x by converting int[] to *char , this is a different story)

+5
source
 #define ISBITSET(x,i) (((x)[(i) / CHAR_BIT] & (1u << ((i) % CHAR_BIT))) != 0) #define SETBIT(x,i) (x)[(i) / CHAR_BIT] |= (1u << ((i) % CHAR_BIT); #define CLEARBIT(x,i) (x)[(i) / CHAR_BIT] &= ~(1u << ((i) % CHAR_BIT)) 
  • Always put brackets around macro arguments
  • always prefer unsigned types for bit operations
  • (1u <CHAR_BIT) - 256 for 8-bit platforms.
  • after the last macro exra appeared
;
0
source

Source: https://habr.com/ru/post/1396027/


All Articles