FirstHack Learn
Log in Sign up free

Operators in C

10 min read · 24 views

Operators in C

An operator is a symbol that tells the compiler to perform a specific operation on one or more values. You already know most of them from school mathematics. The interesting parts of C are the ones that behave slightly differently from what maths taught you, and those are where marks and debugging hours get lost.

Arithmetic operators

Operator Meaning Example with a = 7, b = 2
+ Addition 9
- Subtraction 5
* Multiplication 14
/ Division 3, not 3.5
% Remainder (modulo) 1

The division result is the point. When both operands are integers, C does integer division and truncates towards zero. It does not round. 7 / 2 is 3 and -7 / 2 is -3.

The % operator returns the remainder and works only on integers. Using it on a float is a compile error. It is enormously useful: n % 2 == 0 tests evenness, n % 10 extracts the last digit, and n / 10 removes it.

C
#include <stdio.h>

int main(void)
{
    int number = 4275;

    printf("Number       : %d\n", number);
    printf("Last digit   : %d\n", number % 10);
    printf("Drop a digit : %d\n", number / 10);
    printf("Is it even?  : %d\n", number % 2 == 0);
    printf("Real division: %.2f\n", (float) number / 10);

    return 0;
}

Relational and logical operators

Relational operators compare two values and produce an integer: 1 for true, 0 for false. C has no separate boolean type in its original form, and that is not a detail you can ignore, because it means the result of a comparison is an ordinary number you can print, store or add.

Operator Meaning
== Equal to
!= Not equal to
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to

Logical operators combine conditions. && is AND, || is OR, and ! is NOT. C treats any non-zero value as true and only zero as false, so if (marks) is true whenever marks is not zero.

Both && and || use short-circuit evaluation: they stop as soon as the answer is certain. In a != 0 && b / a > 2, if a is zero the left side is false, so the right side never runs and you avoid a division by zero. Ordering conditions deliberately is a real technique, not an accident.

C
#include <stdio.h>

int main(void)
{
    int marks = 76;
    int attendance = 82;

    printf("marks > 40           : %d\n", marks > 40);
    printf("marks == 76          : %d\n", marks == 76);
    printf("marks != 76          : %d\n", marks != 76);
    printf("eligible (both)      : %d\n", marks >= 40 && attendance >= 75);
    printf("flagged (either)     : %d\n", marks < 40 || attendance < 75);
    printf("not eligible         : %d\n", !(marks >= 40));

    return 0;
}

Increment and decrement

++ adds one, -- subtracts one. Each has two forms, and the difference only shows up when you use the value in a larger expression.

  • Post-increment i++ yields the old value, then increases i.
  • Pre-increment ++i increases i first, then yields the new value.

As a statement on its own, i++; and ++i; do exactly the same thing. Inside an assignment or a function call they do not.

C
#include <stdio.h>

int main(void)
{
    int i = 5;
    int a = i++;
    printf("post: a = %d, i = %d\n", a, i);

    int j = 5;
    int b = ++j;
    printf("pre : b = %d, j = %d\n", b, j);

    int k = 3;
    printf("k++ prints %d, ", k++);
    printf("then k is %d\n", k);

    return 0;
}

a becomes 5 while i becomes 6. b and j are both 6.

⚠️Do not modify the same variable twice in one expression

Expressions such as i = i++ + ++i; or printf("%d %d", i++, i++); have undefined behaviour in C. The standard does not say what happens, so different compilers give different answers and all of them are technically correct. Exam papers love these; real code must never contain them. Split the statement into separate lines.

Assignment operators

= assigns. The compound forms are shorthand: x += 5 means x = x + 5, and the same pattern gives you -=, *=, /= and %=. They are not just shorter to type, they also make the intent obvious and avoid retyping a long variable name incorrectly.

Note that = is an operator with a value, which is why a = b = 0; works: b = 0 evaluates to 0, and that is then assigned to a.

Bitwise operators, briefly

These work on the individual bits of an integer. You do not need them for most first-year assignments, but they appear in embedded systems, graphics, hashing and competitive programming, and questions about them turn up in exams.

Operator Name Effect
& AND Bit is 1 only if both bits are 1
^ XOR Bit is 1 if the two bits differ
~ NOT Flips every bit
<< Left shift Shifts bits left, filling with zeros
>> Right shift Shifts bits right

There is also a bitwise OR, written as a single vertical bar, which sets a bit to 1 if either input bit is 1. Do not confuse the single-character bitwise forms with the double-character logical forms && and the double vertical bar. 5 & 3 is 1, while 5 && 3 is 1 for an entirely different reason.

C
#include <stdio.h>

int main(void)
{
    int a = 12;   /* 1100 in binary */
    int b = 10;   /* 1010 in binary */

    printf("a & b  = %d\n", a & b);
    printf("a ^ b  = %d\n", a ^ b);
    printf("a << 1 = %d\n", a << 1);
    printf("a >> 2 = %d\n", a >> 2);
    printf("odd?     %d\n", a & 1);

    return 0;
}

Shifting left by one multiplies by two; shifting right by one divides by two for non-negative numbers. n & 1 is a fast test for oddness because it simply looks at the lowest bit.

Precedence and associativity

When several operators appear together, precedence decides which binds tighter and associativity decides the direction for equal precedence. Here are the groups you need most, highest first.

Level Operators
1 () function call, array subscript
2 ! ~ unary minus, ++ --, casts
3 * / %
4 + -
5 << >>
6 < <= > >=
7 == !=
8 bitwise AND, then XOR, then OR
9 && then the logical OR
10 ?: conditional
11 = += -= and friends

So 2 + 3 * 4 is 14, and a < b == c < d parses as (a < b) == (c < d), which is almost never what anyone meant. One trap deserves special mention: bitwise AND has lower precedence than ==, so if (flags & 1 == 1) actually means if (flags & (1 == 1)). Write the brackets.

The practical rule is simple. Learn that * and / beat + and -, that comparisons beat && and the logical OR, and that assignment is last. For everything else, add parentheses. Nobody has ever lost a mark for making an expression unambiguous.

Common mistakes

  • Expecting / to give a fraction. avg = total / count; with two int variables truncates. Cast one side: (float) total / count.
  • Using = instead of ==. if (x = 5) assigns 5 and is always true. The compiler often warns; take the warning seriously.
  • Confusing & with &&. Both compile. if (a & b) on the values 2 and 4 gives 0, while if (a && b) gives 1.
  • Modifying a variable twice in one expression. i = i++ + 1; is undefined. Split it up.
  • Applying % to floats. 7.5 % 2 will not compile. Use fmod from math.h if you truly need it.
  • Trusting memorised precedence over brackets. Even experienced programmers add parentheses. Do the same.

Operators are the vocabulary of every expression you will write. Once integer division, short-circuiting and the pre/post distinction feel obvious, most C code becomes readable. Test that on the Practice page.

Create a free account to track what you have finished.