2

I'm reading a code about an implementation of a function, the person who wrote the code, wrote this in his .h:

#define FT_LS_LONG      (1 << 0)
#define FT_LS_RECURSIVE (1 << 1)
#define FT_LS_HIDDEN    (1 << 2)
#define FT_LS_REVERSE   (1 << 3)
#define FT_LS_TIME      (1 << 4)
#define FT_LS_LINE      (1 << 5)

Why did he used bitwise left shift and not something else? And, by what he could have replaced this part of the code? I'm aware that (1 << 0) == 0000 0001 (1 << 1) == 0000 0010, etc.. But I don't get how you can use those.

wwwwwww
  • 29
  • 3

5 Answers5

3

These constructs are typically used in flags that are combined into a single word. They can be combined using the bit-wise OR-operator, e.g.:

int flags = FT_LS_LONG | FT_LS_HIDDEN;

In the code above, the flags variable will be set to 0000 0101. The flags variable can then be tested using the bit-wise AND-operator, e.g.:

if (flags & FT_LS_LONG) { foo(); }

The if-statement will evaluate as true, and the foo() function will be called.

if (flags & FT_LS_TIME) { bar(); }

The if-statement will evaluate as false, and the bar() function will not be called.

Danny Ruijters
  • 3,411
  • 2
  • 18
  • 21
3

It's self-documenting code. 1 could mean anything, while 1 << 0 is most definitely a bit mask. Note that the shift is evaluated at compile-time, since it is an integer constant expression.

A bit more code formatting would have made it all neater:

#define FT_LS_LONG      (1 << 0)
#define FT_LS_RECURSIVE (1 << 1)
#define FT_LS_HIDDEN    (1 << 2)
#define FT_LS_REVERSE   (1 << 3)
#define FT_LS_TIME      (1 << 4)
#define FT_LS_LINE      (1 << 5)

There's no doubt that these are bit masks used to mask different bits of data from the same byte.

Equivalent code could also have been written using hex literals too, it is just a matter of style:

#define FT_LS_LONG      0x01u
#define FT_LS_RECURSIVE 0x02u
#define FT_LS_HIDDEN    0x04u
#define FT_LS_REVERSE   0x08u
#define FT_LS_TIME      0x10u
#define FT_LS_LINE      0x20u
Lundin
  • 195,001
  • 40
  • 254
  • 396
2

He probably has done it because it is more clear. FT_LS_LONG is represented by the first (zero'th) bit. He also could just leave it as # define FT_LS_LONG 1 but than it's less clear as all those macros's are contained within a single byte.

Swedgin
  • 815
  • 1
  • 11
  • 20
-1

Without looking at the original code it's hard to tell but this seems to be defining flags in a way that is readable. The alternative would be use #defines set to 0000001, 0000010,0000100 etc. which is less readable and error prone (if you miss a 0 or a 1 it will be hard to tell where the program is failing)

In the implementation I'd expect to see bit wise ands trying to figure out which flags are On or Off.

Miguel Garcia
  • 1,029
  • 5
  • 14
-1

As other answers suggest this is typically because of using flags, however that's not necessarily the only reason.

For microcontrollers for example address space is extremely precious so they pack multiple properties in a single byte, sometimes they are just boolean flags, sometimes they might be something else, for example a clock division factor, and might consist of a few bits, but because the address space is extremely limited it is stored in the same peripheral configuration register as other flags and/or values so they might be for example 5 bits starting at bit 2 and you might find values such as 0b10101 << 2 or in hex 0x15 << 2.

In the microcontroller case it makes it easier to find in the documentation, you just look at the register and which bit it is in it... as in you don't have to count 0s in binary representation or convert it from hex or even worse from decimal to figure out the corresponding value.

xception
  • 4,241
  • 1
  • 17
  • 27