Operators
Most of C's operators look familiar from other languages. The place people get tripped up is arithmetic on whole numbers — because C's int division isn't the division you learned in school, and knowing exactly when that matters will save you from some genuinely confusing bugs later.
Arithmetic and integer division
When both operands of / are integers, C throws away the fractional part instead of rounding — it doesn't know you wanted a decimal answer unless you tell it:
#include <stdio.h> int main(void) { int a = 7, b = 2; printf("a + b = %d\n", a + b); printf("a / b = %d\n", a / b); printf("a %% b = %d\n", a % b); double x = 7.0, y = 2.0; printf("x / y = %.1f\n", x / y); return 0; }
a + b = 9 a / b = 3 a % b = 1 x / y = 3.5
7 / 2 is 3, not 3.5, because both sides are int. Switch either operand to a double and you get the decimal answer you'd expect. The %% in the format string prints a literal percent sign — printf treats a single % as the start of a format specifier, so writing two escapes it.
% only works on integers. Since C99, division truncates toward zero rather than always rounding down, so the sign of % follows the sign of the left operand — -7 % 2 gives -1, not 1. The identity (a / b) * b + a % b == a always holds, which is a useful way to sanity-check the result if you're unsure.Increment and decrement
i++ and ++i both add one to i, but they hand back different values depending on where you put the ++. Post-increment (i++) evaluates to the old value and then increments; pre-increment (++i) increments first and evaluates to the new value:
#include <stdio.h> int main(void) { int i = 5; printf("i++ gives %d\n", i++); printf("now i is %d\n", i); printf("++i gives %d\n", ++i); printf("now i is %d\n", i); return 0; }
i++ gives 5 now i is 6 ++i gives 7 now i is 7
Comparisons and logic
C doesn't have a dedicated boolean type in the traditional sense (older C, at least — <stdbool.h> adds one, but under the hood it's still built on integers). Every comparison evaluates to an int: 1 for true, 0 for false. That's why you'll sometimes see comparisons printed directly with %d:
#include <stdio.h> int main(void) { int age = 20; int hasLicense = 1; if (age >= 18 && hasLicense) { printf("Can drive.\n"); } else { printf("Cannot drive.\n"); } printf("Result of 5 > 3: %d\n", 5 > 3); printf("Result of 5 == 3: %d\n", 5 == 3); return 0; }
Can drive. Result of 5 > 3: 1 Result of 5 == 3: 0
&& and || both short-circuit, meaning if the left side already decides the answer, the right side never even gets evaluated. In age >= 18 && hasLicense, if age >= 18 were false, C wouldn't bother checking hasLicense at all — which matters if the right-hand expression has side effects or could crash (like dereferencing something that might not exist, a topic you'll hit in the pointers lesson).