-2

I have seen two kinds of bit masking implementations:

  1. The one that uses bitwise shift operator to set flags |= 1 << MASK_VALUE and clear the mask flags &= ~(1 << MASK_VALUE). This is the approach that is used most frequently.
  2. The other one doesn't use bitwise shift operator and only uses logical operators to set flags |= MASK_VALUE and clear the mask flags &= ~(MASK_VALUE)
#define MASK_VALUE 4

int flags = 0;
    
flags |= 1 << MASK_VALUE;
printf("flags |= 1 << MASK_VALUE: %d\n", flags);

flags &= ~(1 << MASK_VALUE);
printf("flags &= ~(1 << MASK_VALUE): %d\n", flags);
    
flags |= MASK_VALUE;
printf("flags |= MASK_VALUE: %d\n", flags);
    
flags &= ~(MASK_VALUE);
printf("flags &= ~(MASK_VALUE): %d\n", flags);

outputs

flags |= 1 << MASK_VALUE: 16
flags &= ~(1 << MASK_VALUE): 0
flags |= MASK_VALUE: 4
flags &= ~(MASK_VALUE): 0

Is there any reason to use bitwise shift operator? Is the first approach preferable over the second one?

FAMO4S
  • 17
  • 4
  • These two implementatios do different things. First one sets or clears single bit by its index. Second one sets or clears a set of bits, which is represented by ones in mask value. – dimich Jul 27 '23 at 23:02
  • In the case of `flags |= 1 << MASK_VALUE` the `MASK_VALUE` is a single *bit position* and is a [misnomer](https://dictionary.cambridge.org/dictionary/english/misnomer). In `flags |= MASK_VALUE;` the `MASK_VALUE` is actually the mask itself, and may comprise any number of bits. – Weather Vane Jul 27 '23 at 23:03
  • @dimich generally the case, but in this case both examples address a _single_ bit, but a different single bit. – Clifford Jul 27 '23 at 23:30
  • @Clifford [here](https://i.ibb.co/vJY9kKc/image.png) is the screenshot from the page. It's page 149 section 6.9 – FAMO4S Jul 28 '23 at 00:14
  • Base64 encoding _expands_ 3 bytes (24 bits) into 4 bytes (32 bits) (and the reverse). This is but one example of why _bit shifting_ is a useful facility. – Fe2O3 Jul 28 '23 at 04:30
  • @Fe2O3 I think the OP is asking why, the shift operator is useful in the context of the code presented in the question, not why it is generally useful or where it might be used. – Clifford Jul 28 '23 at 05:17
  • 1
    @FAMO4S that makes more sense, you posted (and since deleted) an incorrect value for `STATIC` (03 not 04), hence my doubt over plausibility. 1, 2 and 4 are a binary progression, same as `1<<0`, `1<<1` and `1<<2` for bits 0, 1 and 2 respectively. K&R's use of octal rather than hexadecimal is arcane and ill-advised, it's inclusion in the language (at least in that form) is probably regretted. The thing is 4, 04, and 0x4 for example are decimal, octal (base 8) and hexadecimal respectively. Hence for example 08 is an invalid literal value - but that is not really obvious. 8 == 010 in octal. – Clifford Jul 28 '23 at 05:31
  • @FAMO4S. If the K&R example is relevant to your question, you should not include it in the question rather than a comment. When you originally commented, I missed that you were the OP, and thought you were intending it as somehow an answer rather than a clarification - my apologies for that. – Clifford Jul 28 '23 at 05:37

1 Answers1

4

In the first case, MASK_VALUE is misnamed, it is not a mask, it is a bit number.

So for example if you wanted to mask bit 4 you would use a value 1<<4 which is 16.

A bit mask with value 4 would be (1 << 2). So your examples are not semantically identical.

In more realistic code, you might have:

#define BIT_NUM 4
#define BIT_MASK (1 << BIT_NUM)
    
flags |= BIT_MASK;    // set bit 4
flags &= ~(BIT_MASK); // clear bit 4

So the shift is used as a means of calculating a compile time constant, with self documenting code, that is less error prone and more easily maintained than just using the literal value 16 (or more likely for bit masks 0x10u).

It comes into its own when you create more complex masks:

#define BIT_FIELD_A_MSK (0x3u << 8) // b8:b9 field
#define BIT_B_MSK (0x1u << 4) // b4 flag

#define MASK_BITS (BIT_FIELD_A_MSK | BIT_B_MSK) // 0x0310 (bits 4,8 and 9)
Clifford
  • 88,407
  • 13
  • 85
  • 165