Data Types

A data type tells the language (and the programmer) what kind of value is being stored and what operations are valid on it. Type categories, their sizes and their behavior differ noticeably between languages.

A data type classifies a value — common primitive (basic, built-in) types include integers (whole numbers), floating-point numbers (decimals), booleans (true/false), and characters/strings (text). Languages also support composite types (arrays, structures, objects) built up from these basics.

Knowing a value's type tells the language how much memory to reserve for it, what operations are valid (you can't 'multiply' two pieces of text the way you multiply two numbers), and how to interpret its raw bits correctly.

Every value in every program has a type, whether or not the programmer writes it explicitly — a user's age is typically an integer, a product's price is typically a floating-point or fixed-point number, and a person's name is typically a string.

Think of types like different kinds of containers in a kitchen: a container for liquids, a container for dry goods, a container for spices. Each container shape suits what's stored in it and constrains what you can sensibly do with the contents — you wouldn't try to pour dry rice like a liquid.

Each variable's declared type tells the C compiler exactly how many bytes to reserve and how to interpret the bits stored there — an int and a double occupy different amounts of memory and are processed by entirely different CPU instructions.

Integer types often come in multiple sizes (8-bit, 16-bit, 32-bit, 64-bit) and signedness (signed can represent negative numbers, unsigned cannot but gets a larger positive range) — choosing the wrong size can silently truncate or wrap values (integer overflow).

Floating-point numbers (float, double) approximate real numbers using a finite binary representation (IEEE 754 in most languages) and cannot represent every decimal value exactly — 0.1 + 0.2 famously does not equal exactly 0.3 in most languages due to this representation.

A string is, underneath, typically an array or sequence of characters, but different languages represent character encoding differently (ASCII, UTF-8, UTF-16) which affects how many bytes a single 'character' actually occupies, especially for non-English text and emoji.

Some languages distinguish value types (copied when assigned or passed — most primitives in C, Java's primitives) from reference types (the variable holds a reference/pointer to the actual data — objects in Java, most values in Python) which changes what happens when you assign one variable to another.

Comparing floating-point numbers for exact equality (if (a == b)) without accounting for representation imprecision — nearly always a bug; a small tolerance/epsilon comparison is usually needed instead.

Choosing a signed integer type for a value that should never be negative (like an array index or a count) and then not validating against negative input, or vice versa causing unexpected wraparound.

Assuming a 'character' always occupies exactly one byte — true for plain ASCII, false for many Unicode characters encoded in UTF-8 or UTF-16, which can span multiple bytes for a single visible character.

Ignoring integer overflow — adding 1 to the maximum value a type can hold wraps around to a very different value (often a large negative number, or zero) rather than raising an error in many languages.

Choosing double over float for financial or scientific calculations needing more precision, while being aware that even double still has rounding error for many decimal fractions.

Explicitly using a fixed-width integer type (like int32_t in C) in embedded or cross-platform code where the exact size must be guaranteed regardless of compiler or platform.

Validating and sanitizing user input types before using them in calculations, to avoid crashes or silent wraparound from unexpected values.

IEEE 754 floating-point representation Most languages represent floating-point numbers using the IEEE 754 standard, which splits the bits into a sign, an exponent, and a mantissa (fraction) — this binary representation cannot exactly represent most decimal fractions, the same way 1/3 cannot be written exactly in decimal. This is why floating-point rounding error is a language-independent, hardware-level phenomenon, not a bug in any particular language.

Type layout and memory alignment A compiler doesn't just choose how many bytes a type occupies — it also typically aligns that data in memory to addresses that are multiples of the type's size (or the platform's word size), for performance reasons on many CPU architectures. This can introduce padding bytes inside structures, a topic covered fully in the future Memory & Program Execution module.

Boxed vs. unboxed primitives Languages like Java distinguish primitive types (int, stored directly, unboxed) from their object wrapper equivalents (Integer, boxed — stored as a heap object with reference semantics). Autoboxing/unboxing conversions happen automatically in many contexts but carry real performance and memory costs that matter in tight loops or large collections.

Output-based: what does 0.1 + 0.2 == 0.3 evaluate to in most languages, and why?

false in most languages using IEEE 754 double-precision floating-point. Neither 0.1 nor 0.2 can be represented exactly in binary floating-point, so their sum is a value extremely close to, but not bit-for-bit equal to, the closest representable value of 0.3.

What happens when you add 1 to the maximum value of a fixed-size unsigned integer type?

In most languages with fixed-width unsigned integers (like C's unsigned int), the value wraps around to 0 — this is well-defined behavior for unsigned overflow in C, though signed integer overflow in C is undefined behavior, a subtly different and more dangerous case.

Why can a single visible character sometimes take more than one byte to store?

Because many characters, especially outside basic ASCII (accented letters, non-Latin scripts, emoji), require more than one byte to represent in variable-width encodings like UTF-8, or even multiple 16-bit code units in UTF-16 for characters outside the Basic Multilingual Plane.

int count = 10;        // whole number
double price = 19.99;   // decimal number
char grade = 'A';        // single character
bool passed = true;      // true or false