Skip to main content
The ushr (unsigned shift right) operator in Kotlin performs a logical right bitwise shift. It shifts the binary representation of the left operand to the right by the number of bit positions specified by the right operand, filling the newly vacated most significant bits (MSBs) with zeros, regardless of the operand’s original sign.

Syntax

Because ushr is declared with the infix modifier in Kotlin, it allows omitting the dot and parentheses for readability, though standard method invocation remains perfectly valid.

Technical Mechanics

  • Zero Extension: Unlike the shr (shift right) operator, which performs an arithmetic shift and preserves the sign bit (sign extension), ushr strictly performs a zero extension. This means a negative number shifted using ushr will become a positive number, as the MSB (the sign bit) is overwritten with a 0.
  • Supported Types and the Sign-Extension Trap: The ushr operator is defined exclusively for Int (32-bit) and Long (64-bit) types. It is not defined on smaller types like Byte or Short. Attempting to use ushr directly on these types results in a compiler error (Unresolved reference: ushr). While the operand must be explicitly converted first using .toInt() or .toLong(), doing so on a negative number introduces a semantic bug due to sign extension. Calling .toInt() on a negative Byte pads the new 24 upper bits with 1s. To achieve a true 8-bit or 16-bit logical shift, you must apply a bitwise mask (e.g., and 0xFF) to clear the sign-extended bits before shifting:
  • Shift Distance Masking: Kotlin masks the right operand (bitCount) to prevent shifting beyond the bit-width of the left operand.
    • For an Int, the shift distance is masked with 31 (binary 11111), meaning only the lowest 5 bits of the right operand are used. x ushr 32 is equivalent to x ushr 0.
    • For a Long, the shift distance is masked with 63 (binary 111111), using the lowest 6 bits.

Behavior Visualization

Example 1: Positive Integer

When applied to a positive integer, ushr behaves identically to shr because the MSB is already 0.

Example 2: Negative Integer

When applied to a negative integer, the difference between ushr and shr becomes apparent due to the zero-fill behavior.
By contrast, using shr on -2 by 1 would result in -1 (11111111 11111111 11111111 11111111) because it duplicates the 1 in the sign bit.
Tired of Poor Kotlin Skills? Fix That With Deep Grasping!Learn More