C Foundations

Variables & Types

Why this matters

In Python or JavaScript, you can write x = 5 and later x = "hello" – the same name can hold completely different kinds of values, and the language figures it out as it goes. C doesn’t work that way: every variable has one type, fixed the moment you declare it, forever. That’s not an arbitrary restriction. A type tells the compiler exactly how many bytes to set aside for that variable and exactly how to interpret whatever bits end up stored there – and it needs to know that up front, before your program even runs, not figure it out on the fly. This lesson is about what that means concretely, for the handful of types you’ll use constantly.

A variable is a labeled box of a fixed size

When you write int quantity = 3;, three things happen: the compiler reserves a small, fixed-size chunk of memory (a “box”), it remembers that this particular box is called quantity, and it remembers that whatever bits end up in that box should be read as an int. The 3 gets stored into the box as a pattern of bits – specifically, however the number 3 is represented in binary.

This matters because the box’s size is fixed by its type, chosen when you declared it, and can never change. An int box is always the same size, no matter what number you put in it – unlike a Python int, which can grow arbitrarily large automatically. C decided the size up front, at compile time, in exchange for that memory being extremely cheap and fast to use. (What happens if a number doesn’t fit in its box is the subject of a later lesson, on overflow – for now, just hold onto “fixed size, decided in advance.”)

The four types you’ll use constantly

The worked example on the right declares one variable of each of the three most common types, plus there’s a fourth worth knowing about now. Go through them one at a time:

int – a whole number, positive or negative, no decimal point. This is almost always your default choice for counting things. On essentially every machine you’ll use, an int is 4 bytes (32 bits), which gives it a range of roughly -2.1 billion to +2.1 billion – more than enough for counting most things, but not infinite the way a Python integer is.

double – a number that can have a decimal point (a “floating-point” number). Use this for prices, averages, measurements – anything that isn’t naturally a whole number. It’s 8 bytes, and stores roughly 15-17 significant decimal digits, which is precise but, importantly, not exact – double values are frequently very slightly off from the “real” decimal number they’re approximating, the same way 0.1 + 0.2 famously doesn’t print as exactly 0.3 in most languages. You won’t feel this in the exercises ahead, but it’s worth knowing it’s true from the start.

char – a single character, written in single quotes ('B', not "B" – double quotes are for text made of multiple characters, which this course gets to later). Here’s the part that’s genuinely different from most languages you’ve used: a char is not a special “text” type at all. It’s a 1-byte integer, and printing it as a character is just C choosing to display that integer’s value using a standard mapping from numbers to symbols (ASCII) – 'B' and the number 66 are, underneath, the exact same thing. This stops being a curiosity and becomes useful in the last lesson of this module.

float – like double, but 4 bytes instead of 8, with only about 6-9 significant digits. You won’t use this much in this course; prefer double unless you have a specific reason not to (matching hardware, saving memory at large scale). It’s worth knowing it exists mainly so you recognize it when you see it.

Declaring a variable: the pattern

Every declaration in the worked example follows the same shape: type name = value;. Say the type, then a name of your choosing, then = and the starting value, then a semicolon. You can also declare a variable without giving it a value yet (int quantity;), and assign it later on its own line (quantity = 3;) – you actually already did this in the previous lesson’s last exercise, with int n; followed later by reading into it with scanf.

Printing each type needs its own placeholder

Notice the worked example uses a different placeholder in each printf call: %d for the int, %.2f for the double (the .2 means “2 digits after the decimal point” – try removing it and rerunning, to see the difference), and %c for the char. printf doesn’t know your variables’ types on its own – you tell it, one placeholder at a time, and it’s your responsibility to match the placeholder to the actual type. Getting this wrong (printing an int with %c, for instance) compiles without complaint in C and just produces nonsense output – worth remembering the next time something prints strangely.

Try it
Output will appear here.

Exercises