Operators
Arithmetic
#include <stdio.h>
int main() {
int a = 17, b = 5;
printf("%d + %d = %d\n", a, b, a + b);
printf("%d - %d = %d\n", a, b, a - b);
printf("%d * %d = %d\n", a, b, a * b);
printf("%d / %d = %d\n", a, b, a / b); // 3: whole numbers only
printf("remainder of %d / %d = %d\n", a, b, a % b); // 2
printf("%.1f\n", 17.0 / 5); // 3.4
return 0;
}Dividing two integers gives an integer, with the remainder thrown away (the variables lesson showed this). %, the remainder operator, gives what was thrown away.
Using the remainder
#include <stdio.h>
int main() {
int n = 1234;
printf("last digit: %d\n", n % 10);
printf("the rest: %d\n", n / 10);
printf("%d is %s\n", n, n % 2 == 0 ? "even" : "odd");
int hour = 22;
printf("5 hours after %d:00 it is %d:00\n", hour, (hour + 5) % 24);
return 0;
}n % 2 tells even from odd, n % 10 gives the last digit, and % 24 wraps a clock around midnight.
Increment and compound assignment
#include <stdio.h>
int main() {
int score = 10;
score += 5; // score = score + 5, so 15
score -= 3; // 12
score *= 2; // 24
score /= 5; // 4: integer division again
printf("score = %d\n", score);
int x = 5;
int y = x++; // y gets 5, then x becomes 6
int z = ++x; // x becomes 7, then z gets 7
printf("x = %d, y = %d, z = %d\n", x, y, z);
return 0;
}x++ hands over the old value and then adds one; ++x adds one first.
Comparisons give 1 or 0
#include <stdio.h>
int main() {
int age = 19;
printf("%d\n", age >= 18); // 1: true
printf("%d\n", age == 21); // 0: false
printf("%d\n", age >= 13 && age <= 19); // 1: a teenager
printf("%d\n", !(age > 65)); // 1
return 0;
}In C, a comparison produces 1 for true and 0 for false, and any value other than zero counts as true. The if-else lesson puts these to work.
Casts
#include <stdio.h>
int main() {
int total = 7, count = 2;
double avg1 = total / count; // 3.0: divided as integers first
double avg2 = (double) total / count; // 3.5: converted first, then divided
printf("%.1f %.1f\n", avg1, avg2);
double price = 9.99;
printf("%d\n", (int) price); // 9: the fraction is cut off, not rounded
printf("%d\n", (int) (price + 0.5)); // 10: a simple way to round a positive number
return 0;
}A cast, a type in brackets, converts a value to that type. Where it goes matters: (double) total / count converts before dividing, while (double) (total / count) would convert the already-chopped answer.
Precedence
#include <stdio.h>
int main() {
printf("%d\n", 2 + 3 * 4); // 14
printf("%d\n", (2 + 3) * 4); // 20
printf("%d\n", 20 - 10 - 5); // 5: evaluated left to right
printf("%d\n", 100 / 10 / 5); // 2
return 0;
}From the highest precedence to the lowest:
| Level | Operators |
|---|---|
| 1 | brackets (), array index [], postfix ++ and -- |
| 2 | !, prefix ++ and --, unary -, casts, sizeof |
| 3 | *, /, % |
| 4 | +, - |
| 5 | <<, >> |
| 6 | <, <=, >, >= |
| 7 | ==, != |
| 8 | &, then ^, then | |
| 9 | &&, then || |
| 10 | ?: |
| 11 | =, += and the other assignments |
Nobody memorises all of it. When in doubt, add brackets.
Bitwise operators
#include <stdio.h>
int main() {
int a = 12; // binary 1100
int b = 10; // binary 1010
printf("a & b = %d\n", a & b); // 1000, which is 8
printf("a | b = %d\n", a | b); // 1110, which is 14
printf("a ^ b = %d\n", a ^ b); // 0110, which is 6
printf("a << 2 = %d\n", a << 2); // 110000, which is 48
printf("a >> 1 = %d\n", a >> 1); // 110, which is 6
return 0;
}These work on the individual bits of a number: AND, OR, exclusive OR, and shifts left and right. They turn up in systems programming, flags and permissions. Shifting left by n multiplies by 2 to the power n, and x & 1 is 1 exactly when x is odd. Don't confuse & with &&, or | with ||.
sizeof
#include <stdio.h>
int main() {
int scores[5] = {90, 85, 77, 68, 95};
printf("int: %d bytes\n", (int) sizeof(int));
printf("char: %d byte\n", (int) sizeof(char));
printf("double: %d bytes\n", (int) sizeof(double));
printf("scores: %d bytes, %d elements\n", (int) sizeof(scores), (int) (sizeof(scores) / sizeof(scores[0])));
return 0;
}sizeof gives the size of a type or variable in bytes. Sizes can differ between systems, so programs ask sizeof instead of assuming. Dividing an array's size by the size of one element counts its elements. sizeof produces a size_t, printed with %zu; the casts to int here keep the printf simple.