5
$\begingroup$

Many programming languages have built-in support for bitwise operations, often using C's syntax:

  • ~ = NOT
  • & = AND
  • | = OR
  • ^ = XOR
  • << = left shift (multiplication by power of 2)
  • >> = right shift (division by power of 2)

These have various practical uses, for example:

  • Using bit fields to pack multiple Boolean flags into a byte
  • Cryptography (XOR is particularly convenient for this)
  • Compression algorithms
  • Variable-length quantity encoding (including UTF-8 character encoding)

So, I would expect any general-purpose programming language to provide the standard bitwise operations. My question is: What's the benefit of them having dedicated punctuation-based syntax, in a language that's not specifically focused on low-level manipulation of binary data? Would there be a downside to relegating these operations to functions in the language's standard library (perhaps in a module named bitops)? This would free up ~&|^ for other uses, e.g.,:

  • ^ could be a BASIC-style exponentiation operator, or a Pascal-style pointer type sigil.
  • & could be a string/array concatenation operator, distinct from addition, so that you could have both [1, 2] & [3, 4] == [1, 2, 3, 4] and [1, 2] + [3, 4] == [4, 6].

One argument for built-in bitwise operators is that they usually map directly to machine-language instructions, allowing efficient implementation. This may matter for performance-critical code, but is less of a concern for interpreted “scripting” languages.

$\endgroup$
3

1 Answer 1

3
$\begingroup$

Many modern languages support built-in operator overloading (e.g. Python and JavaScript use + for both numeric addition and string concatenation), and often user-defined operator overloading (e.g. C++ and Python). So using these operators for bitwise operations on integers does not preclude using them for other operations on other data types (C++ uses << and >> as I/O operations when the left operand is a stream).

Furthermore, in code that does lots of bitwise operations, requiring use of function calls will result in extremely verbose code where it may be hard to see the patterns. For instance, consider this C code for setting or clearing bit n of a variable

var1 |= 1 << n;
var1 &= !(1 << n);

In functional format:

var1 = bitops.or(var1, bitops.lshift(1, n));
var1 = bitops.and(bitopts.invert(bitops.lshift(1, n)));

Of course, you can hide this complexity in macros or higher-level functions.

The one case you mention is that we might like to use ^ for exponentiation, while XOR is probably the least used bitwise operation. However, some languages already use ** for exponentiation -- bitwise won the battle for single-character operators.

$\endgroup$

Not the answer you're looking for? Browse other questions tagged .