C Programming Exercises for Beginners (With Solutions)
Updated 18 min read Aimerscrew
You can read about C all day, but you only really learn it by writing programs, compiling them and fixing what breaks. This page collects 25 C programming exercises for beginners, each with the expected output and a complete, working solution. They follow the order of this tutorial and get a little harder in every section, so work through them in order or jump to the topic you want to practice.
🌍 Real-life example
Learning C is like learning to ride a bike. Watching videos of cyclists teaches you the idea, but balance only comes once you wobble down the street yourself. These exercises are short, safe rides around the block: a tip calculator, a shipping rule, a step counter and a to-do list file. Small enough to finish in a few minutes, real enough to build your confidence.
How to use these C exercises
Every exercise has a problem statement, the output your program should print, and a link to the lesson that teaches the idea. The solution is hidden behind a Show solution button.
- Write your own program in a
.cfile. - Compile it with warnings turned on:
gcc -Wall -Wextra exercise.c -o exercise, then run it. (Need a refresher? See how to install a C compiler.) - Compare your output with the expected output. Only then open the solution. Your code doesn't need to match mine; if the output matches and there are no warnings, you solved it.
💡 Tip
Stuck for more than 15 minutes? Reread the linked lesson, then try again. That bit of struggle is exactly where the learning happens.
Basics, printf and operator exercises
1. Restaurant tip calculator
A dinner bill is $48.50. Calculate an 18% tip and the total, and print both with two decimal places. Related lesson: format specifiers.
Tip: $8.73
Total: $57.23
Show solution
#include <stdio.h>
int main(void) {
double bill = 48.50;
double tip = bill * 0.18;
double total = bill + tip;
printf("Tip: $%.2f\n", tip);
printf("Total: $%.2f\n", total);
return 0;
}
Tip: $8.73
Total: $57.23
2. Celsius to Fahrenheit
Convert 25 degrees Celsius to Fahrenheit with the formula F = C × 9 / 5 + 32, and print the result with one decimal place. Related lesson: type conversion.
25 C is 77.0 F
Show solution
#include <stdio.h>
int main(void) {
int celsius = 25;
double fahrenheit = celsius * 9.0 / 5.0 + 32.0;
printf("%d C is %.1f F\n", celsius, fahrenheit);
return 0;
}
25 C is 77.0 F
Writing 9.0 instead of 9 matters. With only integers, 9 / 5 is integer division and gives 1, so the formula quietly becomes wrong.
3. Movie length in hours and minutes
A movie runs for 135 minutes. Print its length as hours and minutes using / and %. Related lesson: arithmetic operators.
2 h 15 min
Show solution
#include <stdio.h>
int main(void) {
int runtime = 135;
int hours = runtime / 60;
int minutes = runtime % 60;
printf("%d h %d min\n", hours, minutes);
return 0;
}
2 h 15 min
4. Swap two jersey numbers
Two players want to swap jersey numbers: a is 3 and b is 8. Swap the values of the two variables and print them before and after. Related lesson: assignment operators.
Before: a = 3, b = 8
After: a = 8, b = 3
Show solution
#include <stdio.h>
int main(void) {
int a = 3;
int b = 8;
printf("Before: a = %d, b = %d\n", a, b);
int temp = a;
a = b;
b = temp;
printf("After: a = %d, b = %d\n", a, b);
return 0;
}
Before: a = 3, b = 8
After: a = 8, b = 3
The temporary variable holds the old value of a so it isn't lost when a = b runs.
5. Even or odd with a bitwise check
For the numbers 7, 12 and 0, print whether each one is even or odd. Instead of %, use the bitwise AND operator: a number is odd when its lowest bit is 1. Related lesson: bitwise operators.
7 is odd
12 is even
0 is even
Show solution
#include <stdio.h>
int main(void) {
int numbers[3] = {7, 12, 0};
for (int i = 0; i < 3; i++) {
if ((numbers[i] & 1) == 0) {
printf("%d is even\n", numbers[i]);
} else {
printf("%d is odd\n", numbers[i]);
}
}
return 0;
}
7 is odd
12 is even
0 is even
The parentheses around numbers[i] & 1 are required: == has higher precedence than &.
Conditional exercises
6. Free shipping rule
An online shop charges $5.99 shipping, but shipping is free for orders of $50 or more. Print the shipping cost for an order of $42.00 and one of $65.50, using the ternary operator. Related lesson: ternary operator.
Order $42.00 -> shipping $5.99
Order $65.50 -> shipping $0.00
Show solution
#include <stdio.h>
int main(void) {
double orders[2] = {42.00, 65.50};
for (int i = 0; i < 2; i++) {
double shipping = (orders[i] >= 50.0) ? 0.0 : 5.99;
printf("Order $%.2f -> shipping $%.2f\n", orders[i], shipping);
}
return 0;
}
Order $42.00 -> shipping $5.99
Order $65.50 -> shipping $0.00
7. Leap year checker
A year is a leap year if it is divisible by 4, except years divisible by 100, unless they are also divisible by 400. Check 2024, 1900 and 2000. Related lesson: logical operators.
2024 is a leap year
1900 is not a leap year
2000 is a leap year
Show solution
#include <stdio.h>
int main(void) {
int years[3] = {2024, 1900, 2000};
for (int i = 0; i < 3; i++) {
int year = years[i];
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
printf("%d is a leap year\n", year);
} else {
printf("%d is not a leap year\n", year);
}
}
return 0;
}
2024 is a leap year
1900 is not a leap year
2000 is a leap year
8. Letter grades with switch
Write a function letter_grade(int score) that uses switch on score / 10 to return 'A' (90 to 100), 'B' (80s), 'C' (70s), 'D' (60s) or 'F'. Grade the scores 95, 87, 72 and 40. Related lesson: switch statement.
Score 95 -> grade A
Score 87 -> grade B
Score 72 -> grade C
Score 40 -> grade F
Show solution
#include <stdio.h>
char letter_grade(int score) {
switch (score / 10) {
case 10:
case 9:
return 'A';
case 8:
return 'B';
case 7:
return 'C';
case 6:
return 'D';
default:
return 'F';
}
}
int main(void) {
int scores[4] = {95, 87, 72, 40};
for (int i = 0; i < 4; i++) {
printf("Score %d -> grade %c\n", scores[i], letter_grade(scores[i]));
}
return 0;
}
Score 95 -> grade A
Score 87 -> grade B
Score 72 -> grade C
Score 40 -> grade F
Stacking case 10: and case 9: lets a perfect 100 share the 'A' branch. Because every case ends in return, no break is needed.
Loop exercises
9. Add up 1 to 100
Use a for loop to add every whole number from 1 to 100. Related lesson: for loop.
Sum of 1 to 100 = 5050
Show solution
#include <stdio.h>
int main(void) {
int sum = 0;
for (int n = 1; n <= 100; n++) {
sum += n;
}
printf("Sum of 1 to 100 = %d\n", sum);
return 0;
}
Sum of 1 to 100 = 5050
10. FizzBuzz
The classic interview warm-up. For the numbers 1 to 15, print "Fizz" for multiples of 3, "Buzz" for multiples of 5, "FizzBuzz" for multiples of both, and the number otherwise, all on one line separated by spaces. Related lesson: if-else.
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
Show solution
#include <stdio.h>
int main(void) {
for (int n = 1; n <= 15; n++) {
if (n > 1) {
printf(" ");
}
if (n % 15 == 0) {
printf("FizzBuzz");
} else if (n % 3 == 0) {
printf("Fizz");
} else if (n % 5 == 0) {
printf("Buzz");
} else {
printf("%d", n);
}
}
printf("\n");
return 0;
}
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
Check 15 first. If you test 3 first, 15 prints "Fizz" and never reaches the FizzBuzz branch.
11. Savings goal
You have $200 saved and add $75 every month. Use a while loop to find how many months it takes to reach at least $1,000. Related lesson: while loop.
Goal reached after 11 months with $1025
Show solution
#include <stdio.h>
int main(void) {
int savings = 200;
int months = 0;
while (savings < 1000) {
savings += 75;
months++;
}
printf("Goal reached after %d months with $%d\n", months, savings);
return 0;
}
Goal reached after 11 months with $1025
12. Star staircase
Print a staircase of stars with 4 rows, where row 1 has one star, row 2 has two, and so on. Related lesson: nested loops.
*
**
***
****
Show solution
#include <stdio.h>
int main(void) {
for (int row = 1; row <= 4; row++) {
for (int star = 1; star <= row; star++) {
printf("*");
}
printf("\n");
}
return 0;
}
*
**
***
****
13. Digit sum and reverse
For the number 4096, use one loop to calculate the sum of its digits and the number with its digits reversed. Hint: % 10 gives the last digit and / 10 removes it. Related lesson: while loop.
Digit sum of 4096 = 19
4096 reversed = 6904
Show solution
#include <stdio.h>
int main(void) {
int number = 4096;
int remaining = number;
int digit_sum = 0;
int reversed = 0;
while (remaining > 0) {
int digit = remaining % 10;
digit_sum += digit;
reversed = reversed * 10 + digit;
remaining /= 10;
}
printf("Digit sum of %d = %d\n", number, digit_sum);
printf("%d reversed = %d\n", number, reversed);
return 0;
}
Digit sum of 4096 = 19
4096 reversed = 6904
Working on a copy (remaining) keeps the original number available for the final printf.
Function exercises
14. Is it a prime number?
Write a function bool is_prime(int n) that returns true if n is only divisible by 1 and itself. Use it to print all primes below 30 on one line. Related lessons: functions and return values.
2 3 5 7 11 13 17 19 23 29
Show solution
#include <stdio.h>
#include <stdbool.h>
bool is_prime(int n) {
if (n < 2) {
return false;
}
for (int divisor = 2; divisor * divisor <= n; divisor++) {
if (n % divisor == 0) {
return false;
}
}
return true;
}
int main(void) {
int printed = 0;
for (int n = 0; n < 30; n++) {
if (is_prime(n)) {
if (printed > 0) {
printf(" ");
}
printf("%d", n);
printed++;
}
}
printf("\n");
return 0;
}
2 3 5 7 11 13 17 19 23 29
You only need to test divisors while divisor * divisor <= n: if n had a factor bigger than its square root, it would also have a smaller one you already tested.
15. Factorial with recursion
Write a recursive function that returns n! (n factorial, for example 5! = 5 × 4 × 3 × 2 × 1). Print 0!, 5! and 10!. Related lesson: recursion.
0! = 1
5! = 120
10! = 3628800
Show solution
#include <stdio.h>
long long factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
int main(void) {
int values[3] = {0, 5, 10};
for (int i = 0; i < 3; i++) {
printf("%d! = %lld\n", values[i], factorial(values[i]));
}
return 0;
}
0! = 1
5! = 120
10! = 3628800
The base case n <= 1 stops the recursion. Using long long gives room for bigger results, since factorials grow very fast.
16. Biggest square tile (GCD)
A room is 48 by 18 units. The largest square tile that fits both sides exactly has a side equal to the greatest common divisor (GCD) of 48 and 18. Write int gcd(int a, int b) using Euclid's method: replace (a, b) with (b, a % b) until b is 0. Also test 17 and 5. Related lesson: function parameters.
gcd(48, 18) = 6
gcd(17, 5) = 1
Show solution
#include <stdio.h>
int gcd(int a, int b) {
while (b != 0) {
int remainder = a % b;
a = b;
b = remainder;
}
return a;
}
int main(void) {
printf("gcd(48, 18) = %d\n", gcd(48, 18));
printf("gcd(17, 5) = %d\n", gcd(17, 5));
return 0;
}
gcd(48, 18) = 6
gcd(17, 5) = 1
Changing a and b inside gcd is safe: parameters are copies, so the caller's values never change.
Array exercises
17. Weekly temperature report
Given the daily highs {18, 21, 19, 24, 26, 22, 20}, print the highest, the lowest and the average with one decimal place. Related lesson: arrays.
High: 26
Low: 18
Average: 21.4
Show solution
#include <stdio.h>
int main(void) {
int temps[7] = {18, 21, 19, 24, 26, 22, 20};
int high = temps[0];
int low = temps[0];
int sum = 0;
for (int i = 0; i < 7; i++) {
if (temps[i] > high) {
high = temps[i];
}
if (temps[i] < low) {
low = temps[i];
}
sum += temps[i];
}
printf("High: %d\n", high);
printf("Low: %d\n", low);
printf("Average: %.1f\n", sum / 7.0);
return 0;
}
High: 26
Low: 18
Average: 21.4
Starting high and low at the first element (not at 0) works for any data, even all-negative winter temperatures.
18. Reverse a playlist in place
Write void reverse(int values[], int count) that reverses an array without creating a second one. Test it on the track numbers {3, 8, 1, 9, 4}. Related lesson: arrays and functions.
Before: 3 8 1 9 4
After: 4 9 1 8 3
Show solution
#include <stdio.h>
void reverse(int values[], int count) {
for (int i = 0; i < count / 2; i++) {
int temp = values[i];
values[i] = values[count - 1 - i];
values[count - 1 - i] = temp;
}
}
void print_array(const int values[], int count) {
for (int i = 0; i < count; i++) {
if (i > 0) {
printf(" ");
}
printf("%d", values[i]);
}
printf("\n");
}
int main(void) {
int tracks[5] = {3, 8, 1, 9, 4};
printf("Before: ");
print_array(tracks, 5);
reverse(tracks, 5);
printf("After: ");
print_array(tracks, 5);
return 0;
}
Before: 3 8 1 9 4
After: 4 9 1 8 3
The loop only runs to the middle (count / 2). If it went all the way, every pair would be swapped twice and the array would end up unchanged.
String exercises
19. Count the vowels
Count the vowels (a, e, i, o, u) in "Coffee keeps the world turning". Upper and lower case should both count. Related lesson: strings.
Vowels: 9
Show solution
#include <stdio.h>
#include <ctype.h>
int main(void) {
char sentence[] = "Coffee keeps the world turning";
int count = 0;
for (int i = 0; sentence[i] != '\0'; i++) {
int c = tolower((unsigned char) sentence[i]);
if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
count++;
}
}
printf("Vowels: %d\n", count);
return 0;
}
Vowels: 9
The loop stops at the null terminator '\0', the invisible character that marks the end of every C string.
20. Palindrome checker
A palindrome reads the same forwards and backwards. Write bool is_palindrome(const char word[]) that compares characters from both ends toward the middle, and test it on "level", "radar" and "rocket". Related lesson: string functions.
level -> palindrome
radar -> palindrome
rocket -> not a palindrome
Show solution
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool is_palindrome(const char word[]) {
size_t length = strlen(word);
for (size_t i = 0; i < length / 2; i++) {
if (word[i] != word[length - 1 - i]) {
return false;
}
}
return true;
}
int main(void) {
const char *words[3] = {"level", "radar", "rocket"};
for (int i = 0; i < 3; i++) {
printf("%s -> %s\n", words[i],
is_palindrome(words[i]) ? "palindrome" : "not a palindrome");
}
return 0;
}
level -> palindrome
radar -> palindrome
rocket -> not a palindrome
Pointer exercises
21. Swap with pointers
Exercise 4 swapped two variables inside main. Now write a function void swap(int *a, int *b) that swaps the caller's variables. Related lesson: pass by reference.
Before: home = 10, away = 25
After: home = 25, away = 10
Show solution
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main(void) {
int home = 10;
int away = 25;
printf("Before: home = %d, away = %d\n", home, away);
swap(&home, &away);
printf("After: home = %d, away = %d\n", home, away);
return 0;
}
Before: home = 10, away = 25
After: home = 25, away = 10
Passing &home gives the function the address of the real variable, so *a = ... changes it. Without pointers, the function would only swap its own copies.
22. Cheapest and most expensive price
Write void min_max(const int *prices, int count, int *min, int *max) that walks through the array with pointer arithmetic (no []) and returns both results through the two output pointers. Test it on {12, 7, 30, 18, 9}. Related lesson: pointer arithmetic.
Cheapest: $7
Most expensive: $30
Show solution
#include <stdio.h>
void min_max(const int *prices, int count, int *min, int *max) {
*min = *prices;
*max = *prices;
for (const int *p = prices + 1; p < prices + count; p++) {
if (*p < *min) {
*min = *p;
}
if (*p > *max) {
*max = *p;
}
}
}
int main(void) {
int prices[5] = {12, 7, 30, 18, 9};
int cheapest = 0;
int priciest = 0;
min_max(prices, 5, &cheapest, &priciest);
printf("Cheapest: $%d\n", cheapest);
printf("Most expensive: $%d\n", priciest);
return 0;
}
Cheapest: $7
Most expensive: $30
A C function can return only one value, so "output parameters" like min and max are the usual way to hand back several.
Struct, dynamic memory and file exercises
23. Inventory value
Create a Product struct with a name, a price and a quantity in stock. Store three products in an array, write a function that takes a const Product * and returns its stock value, then print each value and the total. Related lessons: structs and struct pointers.
Notebook: $35.00
Pen: $50.00
Backpack: $49.98
Total stock value: $134.98
Show solution
#include <stdio.h>
typedef struct {
char name[20];
double price;
int quantity;
} Product;
double stock_value(const Product *product) {
return product->price * product->quantity;
}
int main(void) {
Product inventory[3] = {
{"Notebook", 3.50, 10},
{"Pen", 1.25, 40},
{"Backpack", 24.99, 2},
};
double total = 0.0;
for (int i = 0; i < 3; i++) {
double value = stock_value(&inventory[i]);
printf("%s: $%.2f\n", inventory[i].name, value);
total += value;
}
printf("Total stock value: $%.2f\n", total);
return 0;
}
Notebook: $35.00
Pen: $50.00
Backpack: $49.98
Total stock value: $134.98
Passing a pointer avoids copying the whole struct, and const promises the function won't change it. The arrow -> reaches a member through a pointer.
24. A step counter that grows
A fitness app stores daily step counts, but it doesn't know in advance how many days there will be. Start with room for 2 days using malloc, and whenever the array is full, double its size with realloc. Add the counts 8200, 10450, 6900, 12000 and 9100, print a message each time the array grows, then print the average. Don't forget to free the memory. Related lessons: malloc and free and calloc and realloc.
Grew to 4 slots
Grew to 8 slots
Days: 5, average steps: 9330
Show solution
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int new_days[5] = {8200, 10450, 6900, 12000, 9100};
size_t capacity = 2;
int count = 0;
int *steps = malloc(capacity * sizeof *steps);
if (steps == NULL) {
printf("Out of memory\n");
return 1;
}
for (int i = 0; i < 5; i++) {
if ((size_t) count == capacity) {
capacity *= 2;
int *bigger = realloc(steps, capacity * sizeof *bigger);
if (bigger == NULL) {
free(steps);
printf("Out of memory\n");
return 1;
}
steps = bigger;
printf("Grew to %zu slots\n", capacity);
}
steps[count] = new_days[i];
count++;
}
long total = 0;
for (int i = 0; i < count; i++) {
total += steps[i];
}
printf("Days: %d, average steps: %ld\n", count, total / count);
free(steps);
steps = NULL;
return 0;
}
Grew to 4 slots
Grew to 8 slots
Days: 5, average steps: 9330
Notice the separate bigger pointer. If realloc fails it returns NULL but leaves the old block alive; writing steps = realloc(steps, ...) directly would lose your only pointer to it and cause a memory leak.
25. Save and number your tasks
Write three tasks to a file called tasks.txt, one per line. Then open the file again, read it line by line with fgets, and print each task with a number. Related lessons: writing files and reading files.
1. Buy groceries
2. Call the dentist
3. Water the plants
Show solution
#include <stdio.h>
#include <string.h>
int main(void) {
const char *tasks[3] = {"Buy groceries", "Call the dentist", "Water the plants"};
FILE *file = fopen("tasks.txt", "w");
if (file == NULL) {
printf("Could not create tasks.txt\n");
return 1;
}
for (int i = 0; i < 3; i++) {
fprintf(file, "%s\n", tasks[i]);
}
fclose(file);
file = fopen("tasks.txt", "r");
if (file == NULL) {
printf("Could not open tasks.txt\n");
return 1;
}
char line[100];
int number = 1;
while (fgets(line, sizeof line, file) != NULL) {
line[strcspn(line, "\n")] = '\0';
printf("%d. %s\n", number, line);
number++;
}
fclose(file);
return 0;
}
1. Buy groceries
2. Call the dentist
3. Water the plants
fgets keeps the newline at the end of each line. strcspn(line, "\n") finds its position so you can replace it with '\0'.
Common mistakes when solving C exercises
1. Integer division by accident
When both sides of / are integers, C throws away the fraction:
#include <stdio.h>
int main(void) {
printf("%d\n", 9 / 5);
printf("%.1f\n", 9 / 5.0);
return 0;
}
1
1.8
Make at least one side a double (like 5.0) when you need decimals. More in type conversion.
2. Writing = instead of ==
if (score = 100) doesn't compare anything: it assigns 100 to score, and the condition is always true. Compile with -Wall and GCC will warn you ("suggest parentheses around assignment used as truth value").
3. Going one past the end of an array
An array of 5 elements has indexes 0 to 4. A loop like for (int i = 0; i <= 5; i++) reads values[5], which doesn't exist. That's undefined behavior: you may get a garbage value or a crash. Use i < 5.
4. Forgetting & in scanf
scanf("%d", age) passes the value of age where scanf expects an address, which usually crashes. Write scanf("%d", &age). See user input.
5. Ignoring compiler warnings
A program that compiles with warnings isn't "done". Warnings in C often point to real bugs, like a wrong format specifier or an uninitialized variable. Treat every warning as an error until you understand it.
Final challenge
🏋️ Try it yourself
A parking lot charges $3 for the first hour and $2 for each extra hour, with a daily maximum of $15. Create a Car struct with a license plate and the hours parked, write int parking_fee(int hours), and print the fee for three cars: KX-204 (1 hour), LM-881 (4 hours) and TR-530 (9 hours).
Show solution
#include <stdio.h>
typedef struct {
char plate[10];
int hours;
} Car;
int parking_fee(int hours) {
int fee = 3 + (hours - 1) * 2;
if (fee > 15) {
fee = 15;
}
return fee;
}
int main(void) {
Car cars[3] = {
{"KX-204", 1},
{"LM-881", 4},
{"TR-530", 9},
};
for (int i = 0; i < 3; i++) {
printf("%s: %d h -> $%d\n", cars[i].plate, cars[i].hours,
parking_fee(cars[i].hours));
}
return 0;
}
KX-204: 1 h -> $3
LM-881: 4 h -> $9
TR-530: 9 h -> $15
Without the cap, 9 hours would cost 3 + 8 × 2 = $19, so the if lowers it to the $15 daily maximum.
What's next?
Feeling more confident? Review the theory behind everything you just practiced with the top C interview questions and answers, from pointers and memory to static, const and undefined behavior.
Key takeaways
- The fastest way to learn C is to write, compile and run small programs yourself before reading a solution.
- Always compile with gcc -Wall -Wextra and fix every warning; warnings in C often point to real bugs.
- Watch for integer division: make one side a double when you need a decimal result.
- Pass addresses with & when a function must change the caller's variables or return several results.
- Check every malloc, realloc and fopen result for NULL, and free memory and close files when you are done.
- If your output matches the expected output exactly, your solution is correct, even if your code looks different.
Frequently asked questions
How can a beginner practice C programming?
Solve small, focused exercises every day, starting with printf, operators and conditions, then loops, functions and arrays, and finally strings, pointers, structs, dynamic memory and files. Write and compile the code yourself before looking at any solution.
What are good first C programming exercises?
Good first exercises use everyday logic: a tip calculator, a temperature converter, an even-or-odd check, a leap year checker, FizzBuzz, summing numbers with a loop and finding the largest value in an array.
Which C topics are hardest for beginners?
Pointers and dynamic memory are usually the hardest, because mistakes there cause crashes or silent bugs. Practice them with small programs, draw memory diagrams on paper, and always check for NULL.
How many C exercises should I solve per day?
Two or three exercises a day is plenty for most beginners. Short daily practice is better than one long session a week, because you revisit ideas before you forget them.
Do I need to install anything to solve these C exercises?
You need a C compiler such as GCC or Clang, or you can use a free online C compiler in your browser. Compile with -Wall -Wextra so the compiler warns you about common mistakes.