skip to content

Show how to implement a bit-flag set in Kotlin: setting, clearing, toggling, and testing a flag using the infix bit functions.

level: middleimportance: should knowfreq 45%

answer

  1. or sets, and inv() clears, xor toggles, and tests
  2. Each flag = 1 shl position
  3. All-set: (f and combo) == combo
  4. Any-set: (f and combo) != 0
  5. Parenthesize before !=

basics

~10 s

Use one bit per flag. Set a flag with 'or', clear it with 'and' of the inverted mask, toggle with 'xor', and test it with 'and' then compare to zero.

solid answer

~40 s

Represent each flag as a distinct power of two, typically defined with shl: val A = 1 shl 0; val B = 1 shl 1. To SET: flags = flags or A. To CLEAR: flags = flags and A.inv(). To TOGGLE: flags = flags xor A. To TEST: (flags and A) != 0. Combine flags with or. The key idioms are or to add bits, and with an inverted mask to remove bits, xor to flip, and a non-zero and to query. Watch precedence: parenthesize the and before comparing with !=. For type-safe flag sets prefer an EnumSet-style abstraction or Kotlin's @JvmInline value classes wrapping an Int, but the raw integer mask is the underlying mechanism.

code

kotlin · 7 lines
kotlin
var flags = 0
val A = 1 shl 0; val B = 1 shl 1; val C = 1 shl 2
flags = flags or A or C            // 0b101
flags = flags and B.inv()          // clear B (already off)
flags = flags xor A                // toggle A off -> 0b100
val hasC = (flags and C) != 0      // true
val hasAll = (flags and (A or C)) == (A or C) // false

go deeper

for a junior

Can set and test a single flag with or and a non-zero and.

for a middle

Correctly implements set/clear/toggle/test and distinguishes any-set vs all-set with proper masks.

for a senior

Avoids precedence bugs and proposes EnumSet or value-class wrappers for type safety over raw ints.

for a principal

Designs a safe flag API (immutability, exhaustiveness, interop) and reasons about when raw masks are justified.

## The model A **bit flag** stores many boolean options inside one integer, one option per bit. Each flag is a **mask** — an integer with exactly one bit set, usually written `1 shl position`. ```kotlin object Perm { const val READ = 1 shl 0 // 0b0001 const val WRITE = 1 shl 1 // 0b0010 const val EXECUTE = 1 shl 2 // 0b0100 } ``` ## The four core operations - **Set (turn on):** `flags = flags or mask`. `or` forces the bit to 1, leaving others untouched. - **Clear (turn off):** `flags = flags and mask.inv()`. `mask.inv()` is all 1s except that bit; `and` keeps every other bit and forces this one to 0. - **Toggle (flip):** `flags = flags xor mask`. `xor` with 1 flips, with 0 leaves alone. - **Test (is it on?):** `(flags and mask) != 0`. `and` isolates the bit; non-zero means it was set. ```kotlin var flags = 0 flags = flags or Perm.READ or Perm.WRITE // set READ+WRITE -> 0b0011 val canWrite = (flags and Perm.WRITE) != 0 // true flags = flags and Perm.WRITE.inv() // clear WRITE -> 0b0001 flags = flags xor Perm.EXECUTE // toggle EXECUTE on -> 0b0101 ``` ## Testing 'all of' vs 'any of' - **All set:** `(flags and combo) == combo`. - **Any set:** `(flags and combo) != 0`. ## Precedence reminder `flags and mask != 0` parses as `flags and (mask != 0)` and won't compile. Always write `(flags and mask) != 0`. ## Idiomatic alternatives For type safety prefer `EnumSet<T>` (interops with Java) or wrap the mask in a `@JvmInline value class` exposing named operations, so callers never manipulate raw ints. The bit math above is what those abstractions do underneath. ## Summary or = set, and-inverted = clear, xor = toggle, non-zero and = test. These four idioms are the entire vocabulary of flag manipulation.

  • How do you check that BOTH flags A and B are set?
    Build the combined mask and compare for equality: (flags and (A or B)) == (A or B). A non-zero check would only confirm at least one is set.
  • Why use mask.inv() to clear instead of xor?
    and mask.inv() forces the bit to 0 regardless of its current state. xor would only clear it if it was set and would wrongly set it if it was already clear.

Each bit is a light switch in a panel: or flips one on, xor toggles it, and-with-inverse turns it off, and reading one bit checks if its light is on.

saying these in an interview costs you the question

  • Using xor to clear a flag (it toggles, not clears)
  • Writing 'flags and mask != 0' without parentheses
  • Using 'any-set' logic when 'all-set' is required
  • Overlapping/duplicate mask values for different flags
  • Mutating with 'or' but forgetting to reassign the result

context