Operators in Odin
Learn arithmetic, comparison, logical, bitwise, and assignment operators in Odin with runnable Docker examples
Operators are the punctuation of a programming language – the symbols that combine values to compute new ones. Odin’s operator set will feel immediately familiar to C, Go, and Pascal programmers, but it has a few distinctive choices that reflect the language’s commitment to explicit, data-oriented programming.
As an imperative, procedural systems language with a strong static type system, Odin treats operators as strictly typed. You cannot add an i32 to an f64 without an explicit cast, and you cannot mix two distinct types even when they share the same underlying representation. This catches a category of bugs at compile time that dynamic languages defer to runtime – or never catch at all.
This tutorial walks through arithmetic, comparison, logical, bitwise, and compound-assignment operators, plus Odin’s distinction between the % remainder operator and the %% modulo operator – a detail that trips up programmers coming from other C-family languages.
Arithmetic Operators
Odin provides the standard arithmetic operators, with one twist: it splits the modulo operation into two operators that behave differently for negative numbers.
Create a file named operators.odin:
| |
A few details worth highlighting from this example:
%is a format verb inprintf– so to print a literal percent sign we write%%inside the format string. The Odin remainder operator itself is still just%.~is XOR (binary) and bitwise NOT (unary). Odin reuses the same character for both, distinguishing them by arity. Programmers coming from C should note that^is not the XOR operator in Odin –^is the pointer dereference suffix.&~is the AND-NOT operator (also called bit clear).p &~ qclears every bit inpthat is set inq. This is a single operator, not two operators applied in sequence.- Short-circuit evaluation means
false && Xnever evaluatesX. The example above avoids a division-by-zero at runtime because the right side of&&is skipped.
Remainder vs. Modulo
Odin is one of the few mainstream languages that exposes the distinction between remainder (%, sign follows the dividend) and Euclidean modulo (%%, sign follows the divisor). For positive numbers they agree; for negative dividends they differ.
Create a file named modulo.odin:
| |
Use %% when you want a result that is always non-negative for a positive divisor – it’s the right tool for wrapping around a circular buffer or computing array indices. Use % when you genuinely want the truncated-division remainder, which matches the behavior of C’s %.
Running with Docker
| |
Recall from the Hello World tutorial that Odin compiles every .odin file in a directory together as a single package. When running the second example, copy only modulo.odin into /tmp – otherwise both files would be compiled as one package with two main procedures, which would fail.
Expected Output
Running operators.odin produces:
=== Arithmetic ===
17 + 5 = 22
17 - 5 = 12
17 * 5 = 85
17 / 5 = 3
17 % 5 = 2
17.0 / 5.0 = 3.40
-n = -42
=== Comparison ===
17 == 5: false
17 != 5: true
17 < 5: false
17 > 5: true
17 <= 5: false
17 >= 5: true
=== Logical ===
true && false = false
true || false = true
!true = false
short-circuit: false
=== Bitwise (p=12, q=10) ===
p & q = 1000
p | q = 1110
p ~ q = 110
~p = 11110011
p &~ q = 100
p << 1 = 11000
p >> 1 = 110
=== Compound Assignment ===
start: 10
after += 5: 15
after -= 3: 12
after *= 2: 24
after /= 4: 6
=== Precedence ===
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
Running modulo.odin produces:
Positive operands (results agree):
7 % 3 = 1
7 %% 3 = 1
Negative dividend (results differ):
-7 % 3 = -1 (remainder: sign of dividend)
-7 %% 3 = 2 (modulo: sign of divisor)
Negative divisor:
7 % -3 = 1
7 %% -3 = -2
Key Concepts
- Integer division truncates toward zero –
17 / 5is3, not3.4. To get a floating-point result, at least one operand must be a float. %is remainder,%%is modulo – they differ in sign behavior for negative operands. Reach for%%when you need a non-negative result with a positive divisor.~doubles as XOR and bitwise NOT – binary~is XOR, unary~is NOT. Odin does not use^for XOR;^is reserved for pointer-related syntax.&~is a single AND-NOT operator – it clears bits in the left operand that are set in the right operand.- No implicit type coercion – you cannot mix
i32andf64in arithmetic without an explicit cast likef64(x). This applies to all operators, not just arithmetic. - Logical operators short-circuit – the right side of
&&and||is only evaluated when needed, which lets you guard expensive or unsafe expressions behind a precondition. - Compound assignments require a mutable target –
+=,-=,*=,/=,%=,&=,|=,~=,<<=,>>=, and&~=are all supported. - Distinct types respect operators but block cross-type mixing – you can add two
Metersvalues, but the compiler will reject adding aMetersto aSecondseven though both aref64underneath.
Running Today
All examples can be run using Docker:
docker pull primeimages/odin:latest
Comments
Loading comments...
Leave a Comment