Chapter 2 — Variables & Data Types
Programs need to **hold values in memory**. This chapter covers how C represents numbers, characters, and constants — and how big each takes.
What you'll learn
- 1Declare variables of `int`, `float`, `double`, `char`, `_Bool`.
- 2Read sizes with `sizeof` and pick types accordingly.
- 3Use `const` for read-only values.
- 4Read printf format specifiers per type.
Core Concepts
1) Primitive types
| Type | Typical size | Range (approx) | printf |
|---|---|---|---|
| `char` | 1 byte | -128..127 | `%c` (char), `%d` (int promo) |
| `int` | 4 bytes | ±2.1B | `%d` |
| `long` | 4 or 8 bytes | depends on platform | `%ld` |
| `long long` | 8 bytes | ±9.2E18 | `%lld` |
| `float` | 4 bytes | ~7 digits | `%f` |
| `double` | 8 bytes | ~15 digits | `%lf` (scanf) / `%f` (printf) |
| `_Bool` | 1 byte | 0 or 1 | `%d` |
2) `sizeof`
printf("%zu\n", sizeof(int)); // typically 4
printf("%zu\n", sizeof(double)); // typically 8`sizeof` is a compile-time operator; it returns `size_t`, print with `%zu`.
3) `const`
const double PI = 3.14159265;
PI = 3.14; // ❌ compile errorUse `const` when a value should never change after init.
4) Common pitfalls of integer width
`int` is **usually** 32-bit, but not guaranteed. For big values use `long long` or `<stdint.h>` (`int64_t`, `uint32_t`).
Examples
Example 1 — `ex01_variables.c`: declare and print various types
int age = 20;
double height = 1.75;
char grade = 'A';
printf("age=%d height=%.2f grade=%c\n", age, height, grade);**Output**
age=20 height=1.75 grade=AKey: each type uses its own format specifier.
Example 2 — `ex02_types.c`: integer overflow
int max = 2147483647;
printf("max = %d\n", max);
printf("max + 1 = %d\n", max + 1);**Output**
max = 2147483647
max + 1 = -2147483648Key: signed overflow wraps to the negative end — undefined behavior in standard C; gcc happens to wrap.
Example 3 — `ex03_sizeof.c`: type sizes on this machine
printf("int = %zu bytes\n", sizeof(int));
printf("long = %zu bytes\n", sizeof(long));
printf("double = %zu bytes\n", sizeof(double));**Output**
int = 4 bytes
long = 8 bytes
double = 8 bytesKey: don't hard-code sizes; ask `sizeof`.
Example 4 — `ex04_const.c`: const stops accidental writes
const double PI = 3.14159;
double r = 5.0;
printf("area = %.2f\n", PI * r * r);**Output**
area = 78.54Key: `const` makes intent explicit and the compiler your ally.
Common mistakes
- **Wrong format specifier** — `%d` for double prints garbage.
- **Uninitialized variables** — reading them is undefined behavior; always init.
- **Comparing float for equality** — use a small epsilon instead.
- **Confusing `char` and `string`** — `'A'` is a char; `"A"` is a 2-byte string.
- **Assuming int sizes** — for portability use `int32_t` etc.
Recap
- Choose the smallest type that fits — but don't be stingy with `int` for counters.
- `sizeof` tells the truth about the current platform.
- `const` documents intent and prevents bugs.
Try it
cd src
gcc -std=c11 -Wall -o ex01 ex01_variables.c && ./ex01
gcc -std=c11 -Wall -o ex02 ex02_types.c && ./ex02
gcc -std=c11 -Wall -o ex03 ex03_sizeof.c && ./ex03
gcc -std=c11 -Wall -o ex04 ex04_const.c && ./ex04💻 Examples
Compilable, runnable examples — see the output yourself.
#include <stdio.h>
int main(void) {
int age = 20;
int year;
year = 2026;
printf("age: %d\n", age);
printf("year: %d\n", year);
age = age + 1;
printf("next year age: %d\n", age);
return 0;
}
age=20 height=1.75 grade=A#include <stdio.h>
int main(void) {
int score = 95;
float ratio = 0.75f;
double price = 19999.99;
char grade = 'A';
printf(" (%%d): %d\n", score);
printf(" (%%f): %f\n", ratio);
printf(" (%%.2f): %.2f\n", ratio);
printf(" (%%lf): %lf\n", price);
printf(" (%%c): %c\n", grade);
printf(" ASCII (%%d): %d\n", grade);
return 0;
}
max = 2147483647
max + 1 = -2147483648#include <stdio.h>
int main(void) {
printf("char = %zu byte\n", sizeof(char));
printf("short = %zu byte\n", sizeof(short));
printf("int = %zu byte\n", sizeof(int));
printf("long = %zu byte\n", sizeof(long));
printf("float = %zu byte\n", sizeof(float));
printf("double = %zu byte\n", sizeof(double));
int a = 0;
printf(" a : %zu byte\n", sizeof(a));
return 0;
}
int = 4 bytes
long = 8 bytes
double = 8 bytes#include <stdio.h>
#define PI 3.14159
#define MAX_USERS 100
int main(void) {
const int DAYS_IN_WEEK = 7;
double radius = 5.0;
printf("pi(): %f\n", PI);
printf(" (): %d\n", MAX_USERS);
printf("(const): %d\n", DAYS_IN_WEEK);
printf("radius %.1f : %f\n", radius, PI * radius * radius);
/* DAYS_IN_WEEK = 8; // - const */
return 0;
}
area = 78.54📝 Exercises
Try them yourself first, then open the solution to compare.
Problem 1 (hw01.c)
Goal: Declare height (cm) and weight (kg) variables, then print:
- Filename: hw01.c
Height: 175.5 cm
Weight: 68.2 kg▶Toggle solution
#include <stdio.h>
int main(void) {
float height = 175.5f;
float weight = 68.2f;
printf("Height: %.1f cm\n", height);
printf("Weight: %.1f kg\n", weight);
return 0;
}
Height: 175.5 cm
Weight: 68.2 kgProblem 2 (hw02.c)
Goal: For `side = 4` print the cube's volume and surface area.
- Filename: hw02.c
Volume: 64
Surface area: 96▶Toggle solution
#include <stdio.h>
int main(void) {
int side = 4;
int volume = side * side * side;
int surface = 6 * side * side;
printf("Volume: %d\n", volume);
printf("Surface area: %d\n", surface);
return 0;
}
Volume: 64
Surface area: 96Problem 3 (hw03.c)
Goal: Define `LIGHT_SPEED` as `299792458` (m/s) with `#define`, then print how far light travels in one second in kilometers.
- Filename: hw03.c
▶Toggle solution
#include <stdio.h>
#define LIGHT_SPEED 299792458 /* m/s */
int main(void) {
long meters = LIGHT_SPEED;
long km = meters / 1000;
printf("Light travels ~%ld km in one second.\n", km);
return 0;
}
All lecture materials and example code are openly available on GitHub.
View on GitHub ↗