18

Can anyone explain this bitwise operation syntax?

#define Bitset(var,bitno) ((var) |=1UL<<(bitno))

I know it sets the bits of var, but I can't understand the syntax.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
tcop
  • 381
  • 1
  • 2
  • 11
  • 1
    The syntax consists of completely unremarkable C operators. Nothing unusual about it. What exactly do you want explained? If you don't know the meaning of basic C operators, it is something you can read in a *book*. This is not the place for "explain the general expression syntax in C" questions. If you have a problem understanding something specific, then you have to say what it is. – AnT stands with Russia Jan 22 '13 at 20:14
  • It's a macro. Replace the macro name "Bitset" with the characters that follow, substituting the macro's positional parameters for "var" and "bitno". Strip away the unnecessary parens to understand it better. – Hot Licks Jan 22 '13 at 20:14
  • 2
    You might be thrown by the rarely-used "1UL", which is just the literal 1 in unsigned long form. – Hot Licks Jan 22 '13 at 20:17
  • Thanks! It was 1UL that actually messed me up. I just moved to embedded C from ASM and things look scary sometimes. – tcop Jan 22 '13 at 20:31

3 Answers3

33

Let's break it down, piece by piece:

1UL is an unsigned long int with a value of 1 represented at the bit level as:

00000000000000000000000000000001

the << is a "bit shift" operator which will move all the bits in that value above to the left bitno number of times. If it's 1UL<<5, you'll end up with:

00000000000000000000000000100000

Once you have this value, the |= (which is a bitwise OR operation with an assignment) will essentially force the bit of var that's in line with that 1 to be a 1 and wont touch any other bits because (X | 0 = X)

Lets say var is 37 and bitno is 7. Then everything at the bit level will look like this:

00000000000000000000000000100101  // var
00000000000000000000000010000000  // 1UL<<7

00000000000000000000000010100101  // var | (1UL<<7)

Finally, in case it isn't clear, the #define marks Bitset as a function-like macro.

Foggzie
  • 9,691
  • 1
  • 31
  • 48
5

This is a macro. Whenever the preprocessor hits a statement like Bitset(var,bitno) it faithfully replaces it with

var = var | 1UL << (bitno)

Further to explain this.

UL here means Unsigned Long.

Operator | is used for bitwise OR operation. so the variable var is ORed with 1UL << bitno and assigned back to var

Then during runtime or compile time depending on the nature of the program,

Say var is 01000110 and bitno is 5

then 1UL << 5 = 32 or 00100000

then

var = 01000110 | 00100000 

ie var = 01100110

sr01853
  • 6,043
  • 1
  • 19
  • 39
  • @nico I am just competing with others. – sr01853 Jan 22 '13 at 20:18
  • didn't know it was a competition – nico Jan 22 '13 at 20:20
  • @nico People answer so quick. like u commented on me. .\ – sr01853 Jan 22 '13 at 20:21
  • still downvoted even when valid. probably a metaSO question :P – sr01853 Jan 22 '13 at 21:13
  • 1
    This was downvoted because its first iteration did nothing to answer the question. Now that it's edited and fixed, I doubt whoever downvoted will come back. Next time, instead, try to type out a complete answer before submitting it and then take the time to clean it up. The later your response, the further towards the top it will show so don't feel pressure to "compete". – Foggzie Jan 22 '13 at 21:27
1

Say var=8, that is 0000 1000 in binary.

If you do

8 | 16 you will have 0000 1000 | 0001 0000 which will give you 0001 1000, because the | operator sets the bit if either bit is 1.

So you are applying the | operator to your value and 1<<n, that is to 0000 0001 shifted of n bits to the left.

For instance 1 << 3 is 0000 0001 << 2 = 0000 0100.

In essence: doing Bitset(8,3) will generate a mask with only the third bit set by doing 1 << 3, getting 0000 0100. It will then "or" this mask to 8, giving: 0000 1000 | 0000 0100, resulting in 0000 1100, that is, you set the 3rd bit of 8.

nico
  • 50,859
  • 17
  • 87
  • 112