C Syntax & Variables
Types, operators, control flow, functions, and the basics of header files in C.
Basic types
int age = 25; // typically 32-bit signed integer
float price = 19.99f; // 32-bit floating point
double precise = 3.14159; // 64-bit floating point
char grade = 'A'; // a single byte, usually holding an ASCII character
C's int doesn't have a fixed, guaranteed width — it's only guaranteed to be at least 16 bits, and is 32 bits on essentially every modern desktop/server platform. When the exact size actually matters (file formats, network protocols, embedded registers), use the fixed-width types from <stdint.h> instead:
#include <stdint.h>
int32_t userId = 1001; // exactly 32 bits, on every conforming platform
uint8_t flags = 0; // exactly 8 bits, unsigned
int64_t fileSize = 4294967296; // exactly 64 bits
sizeof tells you the actual size (in bytes) of a type on the current platform — useful because you should never assume a size without checking:
printf("%zu\n", sizeof(int)); // commonly 4
printf("%zu\n", sizeof(double)); // commonly 8
Operators
int a = 10, b = 3;
int sum = a + b; // 13
int diff = a - b; // 7
int prod = a * b; // 30
int quot = a / b; // 3 — integer division truncates toward zero
int rem = a % b; // 1 — modulo, only defined for integers
int isEqual = (a == b); // 0 (false)
int isBigger = (a > b); // 1 (true)
int x = 5;
x += 3; // x = 8
x++; // x = 9 (post-increment)
++x; // x = 10 (pre-increment)
7 / 2 evaluates to 3, not 3.5 — integer division always truncates. To get a fractional result, at least one operand must be a floating-point type: 7 / 2.0 gives 3.5.
Control flow
int n = 7;
if (n % 2 == 0) {
printf("even\n");
} else if (n < 0) {
printf("negative\n");
} else {
printf("odd\n");
}
switch (n) {
case 1:
printf("one\n");
break;
default:
printf("something else\n");
break;
}
for (int i = 0; i < 3; i++) {
printf("%d ", i); // 0 1 2
}
int i = 0;
while (i < 3) {
printf("%d ", i);
i++;
}
int j = 0;
do {
printf("%d ", j); // runs at least once, even if the condition is false
j++;
} while (j < 0);
Functions
A function's declaration (a prototype, telling the compiler its name/parameters/return type) can be separate from its definition (the actual body) — this is what lets you call a function before its body appears later in the file, or in a different file entirely.
// Declaration (prototype) — often placed in a header file
int add(int a, int b);
int main(void) {
int result = add(2, 3); // legal — the compiler already knows add's signature
printf("%d\n", result); // 5
return 0;
}
// Definition — the actual implementation
int add(int a, int b) {
return a + b;
}
Unlike C++, plain C has no function overloading — each function name must be unique within its scope, regardless of parameter types.
Header files, briefly
A header file (.h) typically holds function declarations, struct/typedef definitions, and macros shared across multiple .c source files — the actual function bodies live in a corresponding .c file.
math_utils.h:
#ifndef MATH_UTILS_H // "include guard" — prevents this header being processed twice
#define MATH_UTILS_H
int add(int a, int b);
int multiply(int a, int b);
#endif
math_utils.c:
#include "math_utils.h"
int add(int a, int b) {
return a + b;
}
int multiply(int a, int b) {
return a * b;
}
main.c:
#include <stdio.h>
#include "math_utils.h" // quotes for your own headers, angle brackets for system ones
int main(void) {
printf("%d\n", add(2, 3)); // 5
return 0;
}
gcc -std=c17 -Wall -Wextra -o app main.c math_utils.c
The #ifndef/#define/#endif include guard prevents a compile error if the same header is (directly or indirectly) #included more than once in the same translation unit.
Common mistakes
- Writing
if (x = 5)instead ofif (x == 5)— this is a legal assignment expression in C, not a comparison, and it's one of the most common real-world C bugs.-Wallwarns about it; heed the warning. - Forgetting integer division truncates:
9 / 2is4, not4.5. - Forgetting the include guard in a header file, causing "redefinition" errors as soon as the header is included from more than one place.
- Assuming
intis a specific bit width across all platforms instead of checking withsizeofor using<stdint.h>types.
Interview questions
Q: What's the difference between a function declaration and a function definition? A declaration (prototype) tells the compiler a function's name, parameter types, and return type so it can be called before the compiler has seen its actual body — typically placed in a header file. A definition is the actual implementation with a function body, and must exist exactly once across the whole program.
Q: Why does if (x = 5) compile in C, and why is it dangerous?
= is the assignment operator and x = 5 is a valid expression that evaluates to 5 (which is non-zero, hence "true" in a boolean context) — C doesn't distinguish assignment from comparison at the type level the way some languages do. This means a typo (= instead of ==) silently assigns instead of comparing, and the resulting bug can be very hard to spot; compiling with -Wall surfaces it as a warning.