Data Types and Their Sizes
int, char, float, double, signed and unsigned variants, sizeof, and why exam papers built on 16-bit compilers quote different sizes than your machine prints.
Types Are Sizes
A variable is a patch of memory with a name. A type answers the two questions the compiler must settle before it can reserve that patch: how many bytes, and how should the bits be interpreted? Every C type is ultimately a size plus an interpretation, and this lesson gives you the standard's actual guarantees, which matter because exam papers and real machines routinely disagree about the numbers.
The Basic Types
ANSI C gives you four basic building blocks:
char: one byte, holding a character or a very small integer.int: the machine's natural whole-number size.float: a single-precision number with a fractional part.double: a double-precision number, roughly twicefloat's accuracy. The default choice for real-number work, and the one this course uses.
int accepts modifiers that stretch or shrink it: short int, long int, and the modifiers may stand alone as short and long. Sign is a separate axis: short, int, and long are signed by default (they can hold negatives), or unsigned (zero and positives only, with double the positive range). Plain char is the exception — whether it is signed or unsigned is implementation-defined, and on this platform it is unsigned, which is why the ranges program below prints char range: 0 to 255. Combined, declarations read like unsigned long total; or short count;. The floating side has one extension of its own, long double, which appears later in this lesson.
The Three Families, in Exam Vocabulary
Textbooks and question papers sort C's types into three groups, and the words are worth having because questions are phrased in them:
- Primary types, also called fundamental or basic:
char,int,float,double, andvoid, together with theshort,long,signed, andunsignedvariants above. The language provides them. - Derived types: types built out of other types, namely arrays, pointers, and functions. Arrays arrive in chapter 7 and pointers in chapter 11.
- User-defined types: type names you introduce yourself, with
enumlater in this chapter,structandunionin chapter 10, andtypedef, which despite the name creates no new type at all, only a second name for an existing one.
void is the odd member of the primary group: a type with no values, whose job is to say "nothing here". You have been writing it since chapter 1 in int main(void), where it declares that main takes no parameters, and it appears again as the return type of a function that returns nothing. Functions are where it becomes useful, so chapter 9 is where it gets a proper treatment.
Measuring with sizeof
The sizeof operator reports the size in bytes of a type or an object. It is one of the 32 keywords, and it is your instrument for turning size talk into facts:
Run it. On this platform you will see char: 1, int: 4, long: 8, float: 4, double: 8. The %lu specifier prints an unsigned long; storing the sizeof result into an unsigned long variable first keeps the types matched.
What the Standard Actually Promises
Here is the part that separates a memorized answer from a correct one. ANSI C does not fix the size of int. It fixes minimums and an ordering:
charis exactly 1 byte by definition, and a byte is at least 8 bits.intholds at least 16 bits;longholds at least 32.- The sizes never shrink as you go up:
charis no larger thanshort,shortno larger thanint,intno larger thanlong.
Everything else is up to the machine and compiler. On the 16-bit compilers behind many textbooks, Turbo C above all, int is 2 bytes and ranges from -32768 to 32767. On this platform, and on essentially every modern desktop, int is 4 bytes with a range of about plus or minus 2.1 billion.
So when an exam asks "what is the size of int?", the honest answer is "at least 16 bits; commonly 2 bytes on old 16-bit compilers and 4 bytes on modern machines". Papers keyed to the textbook may expect "2 bytes"; now you know why, and you can give the expected number while writing programs that never depend on it.
Ranges, and the Header That Knows Them
Ranges follow from sizes. A 2-byte int spans -32768 to 32767; a 4-byte int spans -2147483648 to 2147483647; unsigned shifts the whole span above zero, so a 4-byte unsigned int reaches 4294967295. You do not memorize these per machine: the standard header <limits.h> defines them as symbolic constants.
Note %u for the unsigned value. What happens when arithmetic exceeds these limits is a story with two very different endings, one defined and one not, and it gets its own treatment in the operators chapter.
char Is an Integer in a Costume
char deserves a closer look: it holds a small integer that is usually interpreted as a character code. The character constant 'A' is just the integer 65 in the machine's character set. Both faces are printable:
%c shows the costume, %d shows the integer underneath. This dual nature is not a quirk to tolerate; the strings chapter and every character-processing exam question lean on it directly.
float vs double vs long double
Both hold fractional numbers, trading memory for precision: float gives about 6 reliable decimal digits in 4 bytes, double about 15 in 8 bytes. ANSI C's library and its conversion rules are built around double, literals like 7.5 are double, and the math functions take and return double, so the course default is simple: use double unless a specific reason says otherwise. Why floating-point numbers are approximate at all, and the surprises that causes, is a deep enough topic that it closes the course.
There is a third rung above double: long double, which the standard requires to be at least as precise as double and lets the implementation make better. It is the most machine-dependent type in the language. Compilers have shipped it as 8 bytes (identical to double), as an 80-bit format padded out to 12 or 16, and as a genuine 128-bit format, and the number of usable digits changes with each. <float.h> is the header that reports the truth for whatever you are compiling on, as DBL_DIG and LDBL_DIG, in the same spirit as <limits.h> for the integers.
Two details of using it are worth having now: a long double constant takes the suffix L, as in 1.25L, and printf needs %Lf rather than %f, because the argument is genuinely wider.
double: 8
long double: 16
wide = 1.25
Sixteen bytes here; do not carry that number to another machine. In practice long double earns its keep rarely, and reaching for it is usually a sign that the real problem is an algorithm losing precision rather than a type that is too narrow.
Key Takeaways
- A type fixes a size in bytes and an interpretation of the bits;
sizeofmeasures it. - The basic types are
char,int,float,double, withshort,long,signed,unsignedas integer modifiers. - Exam vocabulary sorts types into primary (
char,int,float,double,void), derived (arrays, pointers, functions), and user-defined (enum,struct,union,typedef). - ANSI C guarantees minimums, not exact sizes:
charis 1 byte,intat least 16 bits,longat least 32, never shrinking up the ladder. Old 16-bit compilers have 2-byteint; this platform has 4. <limits.h>names each integer type's range: INT_MIN, INT_MAX, UINT_MAX, and friends;<float.h>does the same job for the floating types.charis a small integer wearing a character costume:%cprints the character,%dthe code.- Prefer
doubleoverfloat; the language is built around it. Above it sitslong double, the most machine-dependent type in C, written with anL-suffixed constant and printed with%Lf.
How did you find this lesson?
Your rating helps us improve the content.
Create an account to track your progress and access interactive exercises. Already have one? Sign in.
Data Types and Their Sizes - Quiz
Test your understanding of the lesson.
Practice Exercises
Measure the Machine
Use sizeof to report the size of five types on this platform, one per line, in the exact format shown. Store each sizeof result in an unsigned long and print it with %lu so the types match.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!