The VikiD Truth

Knowledge base / Computing / C & systems languages

computingFreedom | Build | Picolisp | Picolisp Machine | Pil Sources | Linux | BASH | C-Programmming | Operating Systems | Javascipt | Emacs | vim | Pharo Smalltalk | Computer Security | Python | The Compiler | Identifiers | Literals | storage_linkage |

Operators

Here is the truth about operators in C: they are just functions in disguise, and two things about them trip up everyone: precedence (who binds tighter) and evaluation order (who runs first), which are not the same question. The tables below (as images) are the quick reference; the prose here is what the tables cannot show.

What it is, in plain words

An operator is a symbol that combines values into a new value: +, *, =, &&, <<, ?:. C has an unusually rich set, grouped by job:

Each operator has a precedence (how tightly it binds) and an associativity (which way it groups when precedences tie). a + b * c is a + (b * c) because * binds tighter; a = b = c is a = (b = c) because = groups right to left.

Why it matters

An everyday analogy: order of operations at the till

A supermarket till applies discounts in a fixed order no matter how you stack the coupons: that fixed order is precedence. Whether the cashier scans the milk or the bread first, when it makes no difference to the total, is evaluation order; the shop does not promise one. Problems come when you assume the scan order changes the total, as with a[i] = i++.

A hands-on example

#include <stdio.h>
int main(void) {
    int x = 6;
    printf("%d\n", x & 1 == 0);     /* prints 0: parsed as x & (1==0), the trap */
    printf("%d\n", (x & 1) == 0);   /* 1: x is even, so its low bit really is 0 */

    int flags = 0;
    flags |= 1 << 2;                /* set bit 2  -> 4 */
    flags |= 1 << 4;                /* set bit 4  -> 20 */
    printf("flags = %d, bit2 set? %d\n", flags, (flags >> 2) & 1);

    int a = 5;
    int b = (a > 3) ? 100 : -100;   /* ternary: a small if-expression */
    printf("%d\n", b);
}
gcc -std=c23 -Wall -Wextra ops.c -o ops && ./ops

Turn on -Wall and GCC warns about the precedence trap on the first line before it ever runs. That warning has saved more programs than any table.

Compare PicoLisp, which sidesteps the whole problem: there are no operators and no precedence, only functions in prefix form. (+ a (* b c)) says exactly what it means, and (& x 1) cannot be misread. The parentheses are the precedence, which is one reason Lispers stop worrying about it.

Common misconceptions

Connections

The reference tables

arithmetic

ass

bit

dat

log

mis

rel

Last edited · 2 revisions

Tags: #Computing