We derive it from first principles — counting bit patterns.
Unsigned (unsigned char, size_t, …): every pattern is a non-negative value.
range=[0,2n−1]Why −1? Because zero eats one of the 2n slots, so the largest value is one less than the count.
Signed (two's complement, what C uses in practice): one bit's "weight" is made negative so we can encode negatives. We split the 2n patterns into negatives and non-negatives:
range=[−2n−1,2n−1−1]
Why this is asymmetric (one more negative than positive)? The pattern 1000…0 is reserved for the most-negative value; zero sits on the positive side, "using up" one positive slot. So you get 2n−1 negatives but only 2n−1−1 positives.
With n bits, how many distinct bit patterns exist?
2n
Range of an n-bit unsigned integer?
[0,2n−1]
Range of an n-bit signed (two's complement) integer?
[−2n−1,2n−1−1]
Why is signed range asymmetric (one more negative)?
The pattern 1000…0 encodes the most-negative value, and 0 sits on the positive side using a slot.
Range of signed char (8 bits)?
[−128,127]
Range of unsigned char (8 bits)?
[0,255]
Range of a 32-bit int?
[−2147483648,2147483647]
Which type's sizeof is guaranteed to be 1 by the standard?
char
Ordering of integer sizes guaranteed by C?
char ≤ short ≤ int ≤ long ≤ long long
IEEE-754 float bit layout (sign/exp/mantissa)?
1 / 8 / 23, bias 127
IEEE-754 double bit layout?
1 / 11 / 52, bias 1023
Value formula of a normalized IEEE-754 number?
(−1)s×(1.f)2×2e−bias
Why does float have ~7 decimal digits of precision?
24 mantissa bits × log10(2) ≈ 7.2
Approx decimal digits of double precision?
~15–16 (53 bits × log10(2))
What is size_t?
An unsigned type large enough to hold any object's size; returned by sizeof.
printf format specifier for size_t?
%zu
Why is "size_t i; i >= 0" a bug in a countdown loop?
Unsigned can never be < 0, so it's always true → infinite loop and wrap-around.
Why is 0.1+0.2 != 0.3 in C?
0.1 and 0.2 have no finite binary representation, so they're rounded.
Recall Feynman: explain to a 12-year-old
Imagine little labelled boxes. A char box is tiny — it fits one letter or a small number. An int box is bigger — it fits normal counting numbers. A double box is special: instead of just counting, it remembers a number in "scientific notation" form (some digits + where the dot goes), so it can hold really big or really tiny numbers but with only about 15 trustworthy digits. size_t is the box we use to say "how big is this thing?" — and since something's size is never negative, that box only holds 0 and up. The label on the box tells the computer how big the box is and how to read what's inside.
Dekho, C me har variable ka ek data type hota hai, aur ye basically ek contract hai jo compiler ko do cheez batata hai: kitne bytes ki memory lena hai, aur un bits ko kaise padhna hai (integer, character, ya floating number). Same bit pattern 0100 0001 ko int samjho to 65, char samjho to 'A' — type hi decide karta hai matlab. Isiliye type ko ek "lens" samajh sakte ho.
Integer types ka range rote-ratane ki zaroorat nahi, derive karo. n bits se 2n patterns bante hain. Agar unsigned hai to range [0,2n−1] (zero ek slot kha jaata hai isliye −1). Agar signed (two's complement) hai to range [−2n−1,2n−1−1] — yaani ek negative number zyada hota hai positive se, kyunki pattern 1000...0 sabse chhota negative banata hai. Isse signed char ka range [−128,127] aur int ka [−2.1 billion, +2.1 billion] nikalta hai. Yaad rakho: standard sirf sizeof(char)==1 guarantee karta hai, int har jagah 4 bytes ho — ye assume mat karna.
float aur double ko samjho scientific notation jaisa: sign + mantissa (digits) + exponent (scale). Formula: (−1)s×1.f×2e−bias. float me 24 mantissa bits → 24×0.301≈7 decimal digits ki precision, double me ~15-16. Isiliye 0.1 + 0.2 == 0.3false aata hai — kyunki 0.1 binary me exactly store hi nahi hota, thoda rounding error aa jaata hai. Float compare karne ke liye fabs(a-b) < epsilon use karo, kabhi == nahi.
Last me size_t: ye ek unsigned type hai jo sizeof aur strlen return karte hain, aur itna bada hota hai ki kisi bhi object ka size store kar sake (64-bit machine pe 8 bytes). Size kabhi negative nahi hota, isiliye unsigned. Ek common bug: size_t i use karke i >= 0 likhoge to wo hamesha true rahega → infinite loop. Print karne ke liye %zu lagao. Bas itna samajh lo to data types ka 80% kaam ho gaya.