Data Types
Data type is not a detail.
Data type is a contract.
It defines:
- what a value means
- how much space it takes
- which operations make sense
- what kind of bug can grow from it
When you understand data types well, you stop programming only on the surface and start understanding how the machine actually sees what you wrote.
And that changes everything.
Before talking about types: everything becomes bits
Section titled “Before talking about types: everything becomes bits”At the end of the day, memory does not know what int, float, char, or bool means.
It only stores bits.
A bit is the smallest unit of digital information:
01
Eight bits make one byte.
1 bit = 0 or 18 bits = 1 byte1024 bytes = 1 KB1024 KB = 1 MBExample of one byte:
01000001That same byte can be interpreted in multiple ways:
- as decimal number
65 - as hexadecimal
0x41 - as ASCII character
'A'
Notice the core idea:
the bits are the same; meaning changes based on type and context.
Data representation: memory does not “see” semantics
Section titled “Data representation: memory does not “see” semantics”Look at this 1-byte block:
Bits: 01000001Dec: 65Hex: 0x41ASCII: 'A'Memory does not know whether this is a letter or a number.
That is decided by:
- the type
- the instruction being used
- the way the value is read
That is why characters have interchangeable numeric values.
In ASCII:
'A'=65'B'=66'a'=97'0'=48
For the full table, see ASCII Table.
Mental diagram: same data, different interpretations
Section titled “Mental diagram: same data, different interpretations”Address: 0x1000
+--------+| 01000001 |+--------+
If read as unsigned char -> 65If read as ASCII char -> 'A'If read as raw binary -> 01000001This is one of the most important ideas in all of computing.
Integers
Section titled “Integers”Integers represent values with no fractional part.
Classic examples:
- age
- quantity
- retries
- stock
- position
Integer sizes in the main languages
Section titled “Integer sizes in the main languages”In C, the exact size depends on the platform and compiler, but the standard guarantees minimum sizes.
char // at least 8 bitsshort // at least 16 bitsint // at least 16 bitslong // at least 32 bitslong long // at least 64 bitsIn C++, the base idea is similar to C:
charshortintlonglong longBut C++ gives you safer casting tools and modern library utilities.
JavaScript
Section titled “JavaScript”JavaScript is very different.
Most regular numbers are Number, which uses 64-bit IEEE 754 floating point.
That means:
- small integers usually work well
- decimals exist
- very large integers lose precision
console.log(typeof 10); // "number"console.log(typeof 10.5); // "number"For truly large integers:
const id = 9007199254740993n;console.log(typeof id); // "bigint"Python
Section titled “Python”Python abstracts more.
int in Python grows as needed.
x = 10y = 10**100
print(type(x)) # <class 'int'>print(type(y)) # <class 'int'>That is great for ergonomics, but it does not mean zero cost.
Huge integers consume more memory and more processing.
Signed and unsigned integers
Section titled “Signed and unsigned integers”In languages like C and C++, this matters a lot.
Signed
Section titled “Signed”Allows negative and positive numbers.
Unsigned
Section titled “Unsigned”Allows only zero and positive values.
Example with 8 bits:
unsigned 8 bits: 0 to 255signed 8 bits: -128 to 127How negative values are stored: two’s complement
Section titled “How negative values are stored: two’s complement”The most common way to represent negative integers is two’s complement.
Example with 8 bits:
5 = 00000101 -5 = 11111011How to build -5 in two’s complement:
5 in binary: 00000101invert the bits: 11111010add 1: 11111011This matters because overflow, casting, and binary arithmetic depend on this representation.
Real example in C
Section titled “Real example in C”#include <stdio.h>
int main(void) { signed char a = -5; unsigned char b = 250;
printf("a = %d\n", a); printf("b = %u\n", b); return 0;}Overflow: when the value does not fit
Section titled “Overflow: when the value does not fit”A type has limits.
If you try to store a value beyond those limits, something breaks.
Conceptual example with unsigned char:
Maximum: 255
255 + 1 = 0 // wraparound in unsigned arithmeticExample in C:
#include <stdio.h>
int main(void) { unsigned char x = 255; x = x + 1; printf("%u\n", x); // usually 0 return 0;}With signed integers, overflow can be even more dangerous because undefined behavior enters the picture in C and C++.
Decimal to binary: integer part
Section titled “Decimal to binary: integer part”If you want to manually convert a decimal integer to binary, divide by 2 and collect the remainders.
Example with 13:
13 / 2 = 6 remainder 1 6 / 2 = 3 remainder 0 3 / 2 = 1 remainder 1 1 / 2 = 0 remainder 1
Reading bottom to top:13 = 1101Decimal fraction to binary
Section titled “Decimal fraction to binary”For fractions, multiply by 2 and observe the integer part.
Example with 0.625:
0.625 * 2 = 1.25 -> 10.25 * 2 = 0.5 -> 00.5 * 2 = 1.0 -> 1
0.625 = 0.101 in binarySo:
10.625 = 1010.101Floating-point numbers
Section titled “Floating-point numbers”This is where many people get hit without realizing it.
Floating-point does not represent “any decimal exactly.”
It represents binary approximations.
That is why cases like this exist:
console.log(0.1 + 0.2); // 0.30000000000000004print(0.1 + 0.2) # 0.30000000000000004#include <iostream>
int main() { std::cout << (0.1 + 0.2) << '\n';}How a float is split in memory
Section titled “How a float is split in memory”In IEEE 754, a 32-bit float is usually organized like this:
31 23 0+-----------+-----------+| sign | exponent | mantissa |+-----------+-----------+
1 bit 8 bits 23 bitsFor a 64-bit double:
63 52 0+------------+---------------------+| sign | exponent | mantissa |+------------+---------------------+
1 bit 11 bits 52 bitsThis explains why:
- float comparisons can fail
- precision is limited
- using float for money is a trap
Example of dangerous comparison
Section titled “Example of dangerous comparison”a = 0.1 + 0.2b = 0.3
print(a == b) # FalseBetter approach:
import math
print(math.isclose(0.1 + 0.2, 0.3)) # TrueIn C++:
#include <cmath>#include <iostream>
int main() { double a = 0.1 + 0.2; double b = 0.3; std::cout << std::boolalpha << (std::fabs(a - b) < 1e-9) << '\n';}Money: use a proper decimal strategy or integer minor units
Section titled “Money: use a proper decimal strategy or integer minor units”Practical rule:
$10.99as1099cents- or a proper decimal type in your chosen stack
JavaScript example using cents:
const priceInCents = 1099;const quantity = 3;
const total = priceInCents * quantity;console.log(total); // 3297console.log((total / 100).toFixed(2)); // "32.97"Python example:
price_cents = 1099quantity = 3
total_cents = price_cents * quantityprint(total_cents) # 3297print(total_cents / 100) # 32.97Characters: letters are also numbers
Section titled “Characters: letters are also numbers”This matters a lot.
A character is not magic. It is also represented numerically.
In ASCII:
'A'=65'B'=66'Z'=90'a'=97'0'=48
Visual example:
'A'Decimal: 65Hex: 0x41Bin: 01000001You mentioned “A = 52”, but the correct ASCII value is 65.
52 in ASCII is the character '4'.
Code: character to number and number to character
Section titled “Code: character to number and number to character”#include <stdio.h>
int main(void) { char c = 'A'; printf("%c\n", c); // A printf("%d\n", c); // 65 return 0;}#include <iostream>
int main() { char c = 'A'; std::cout << c << '\n'; std::cout << static_cast<int>(c) << '\n';}JavaScript
Section titled “JavaScript”const c = 'A';
console.log(c.charCodeAt(0)); // 65console.log(String.fromCharCode(65)); // APython
Section titled “Python”print(ord('A')) # 65print(chr(65)) # AASCII versus Unicode
Section titled “ASCII versus Unicode”ASCII covers the classic 128 codes.
Great for understanding the foundation.
But modern software usually needs Unicode, because:
- accents exist
- emojis exist
- many writing systems exist
ASCII is the starting point.
Unicode is the real world.
Even so, understanding ASCII is still extremely valuable because it helps you understand:
- character comparison
- basic ordering
- parsing
- byte manipulation
- text serialization
Strings: text is not just “a bunch of letters”
Section titled “Strings: text is not just “a bunch of letters””A string is a sequence of characters.
But the implementation varies a lot by language.
In C, a string is an array of char terminated by a null byte '\0'.
#include <stdio.h>
int main(void) { char name[] = "Edu";
printf("%c\n", name[0]); // E printf("%c\n", name[1]); // d printf("%c\n", name[2]); // u printf("%d\n", name[3]); // 0 -> '\0' return 0;}Diagram:
name = "Edu"
+-----+-----+-----+------+| 'E' | 'd' | 'u' | '\0' |+-----+-----+-----+------+In C++, you may use char[], const char*, or std::string.
#include <iostream>#include <string>
int main() { std::string name = "Edu"; std::cout << name.size() << '\n'; // 3}JavaScript
Section titled “JavaScript”Strings in JavaScript are immutable.
const name = "Edu";
console.log(name[0]); // Econsole.log(name.length); // 3Python
Section titled “Python”Strings in Python are also immutable.
name = "Edu"
print(name[0]) # Eprint(len(name)) # 3Booleans
Section titled “Booleans”Boolean models binary state.
true / false1 / 0on / offactive / inactiveIn C:
#include <stdbool.h>#include <stdio.h>
int main(void) { bool active = true; printf("%d\n", active); // 1 return 0;}In JavaScript:
const active = true;console.log(typeof active); // booleanIn Python:
active = Trueprint(type(active)) # <class 'bool'>Null, None, undefined, and friends
Section titled “Null, None, undefined, and friends”This is where a lot of confusion lives.
Plain C often works with null pointers:
int *ptr = NULL;Modern C++ uses nullptr:
int* ptr = nullptr;JavaScript
Section titled “JavaScript”JavaScript has both null and undefined.
let a = null;let b;
console.log(a); // nullconsole.log(b); // undefinedPython
Section titled “Python”Python uses None.
value = NoneMental rule:
- absence of value is not the same as zero
- absence of value is not an empty string
- absence of value is not
false
Casting and conversion
Section titled “Casting and conversion”Now we get to a critical part.
Casting is the act of converting one type into another.
It can be:
- implicit
- explicit
- safe
- dangerous
Implicit casting
Section titled “Implicit casting”The language converts for you.
Sometimes it helps.
Sometimes it plants a bomb.
Example in C
Section titled “Example in C”int a = 10;double b = a; // implicit conversion from int to doubleExample in JavaScript
Section titled “Example in JavaScript”console.log("5" + 1); // "51"console.log("5" - 1); // 4That happens because JavaScript performs implicit coercion.
Powerful.
Also a bug factory if used carelessly.
Explicit casting
Section titled “Explicit casting”You make the conversion intention obvious.
#include <stdio.h>
int main(void) { double x = 3.99; int y = (int)x; printf("%d\n", y); // 3 return 0;}Prefer static_cast over C-style casts when possible:
#include <iostream>
int main() { double x = 3.99; int y = static_cast<int>(x); std::cout << y << '\n'; // 3}JavaScript
Section titled “JavaScript”console.log(Number("42")); // 42console.log(parseInt("42", 10)); // 42console.log(parseFloat("3.14")); // 3.14Python
Section titled “Python”print(int("42")) # 42print(float("3.14")) # 3.14print(str(42)) # "42"Dangerous conversions
Section titled “Dangerous conversions”Losing the fractional part
Section titled “Losing the fractional part”double price = 19.99;int truncated = static_cast<int>(price); // 19Narrowing overflow
Section titled “Narrowing overflow”#include <stdio.h>
int main(void) { int x = 300; unsigned char y = (unsigned char)x; printf("%u\n", y); // may become 44 return 0;}Because:
300 % 256 = 44Invalid string to number
Section titled “Invalid string to number”value = "abc"# int(value) -> ValueErrorconsole.log(Number("abc")); // NaNNaN: a number that is not a number
Section titled “NaN: a number that is not a number”In JavaScript:
const value = Number("abc");
console.log(value); // NaNconsole.log(Number.isNaN(value)); // trueThat kind of case must be handled before business logic continues.
Hexadecimal and memory reading
Section titled “Hexadecimal and memory reading”Hex shows up all the time because it maps very well to bytes.
Each hexadecimal digit represents 4 bits.
Binary: 11111111Hexadecimal: FFDecimal: 255Conversion:
1111 1111 F FAnother example:
0100 0001 4 1
0x41 = 65 = 'A'Endianness: byte order
Section titled “Endianness: byte order”When a value occupies more than 1 byte, the storage order matters.
Example with 0x12345678:
Big-endian
Section titled “Big-endian”+------+------+------+------+| 12 | 34 | 56 | 78 |+------+------+------+------+Little-endian
Section titled “Little-endian”+------+------+------+------+| 78 | 56 | 34 | 12 |+------+------+------+------+This appears in:
- serialization
- networks
- binary file reading
- interoperability between systems
Type size in practice
Section titled “Type size in practice”Example in C:
#include <stdio.h>
int main(void) { printf("char: %zu\n", sizeof(char)); printf("short: %zu\n", sizeof(short)); printf("int: %zu\n", sizeof(int)); printf("long: %zu\n", sizeof(long)); printf("long long: %zu\n", sizeof(long long)); printf("float: %zu\n", sizeof(float)); printf("double: %zu\n", sizeof(double)); return 0;}Example in C++:
#include <iostream>
int main() { std::cout << sizeof(char) << '\n'; std::cout << sizeof(int) << '\n'; std::cout << sizeof(double) << '\n';}How to model real data
Section titled “How to model real data”Before choosing a type, ask:
- Is this quantity, identity, text, state, date, or money?
- Will I calculate with it?
- Is there a known limit?
- Do I need exact precision?
- Can the value be missing?
- Does this come from user input, API, or file?
Those questions prevent a lot of messy code.
Examples of correct modeling
Section titled “Examples of correct modeling”name -> stringage -> integeractive -> booleancreatedAt -> date/timeorderId -> string or domain integeramountCents -> integerpaid -> booleanstatus -> enum or validated stringProduct
Section titled “Product”sku -> stringstock -> integerpriceCents -> integerMini lab of examples
Section titled “Mini lab of examples”C: character and integer share the same numeric base
Section titled “C: character and integer share the same numeric base”#include <stdio.h>
int main(void) { char c = 'A'; int code = c;
printf("char: %c\n", c); printf("code: %d\n", code); return 0;}C++: explicit truncation
Section titled “C++: explicit truncation”#include <iostream>
int main() { double ratio = 9.87; int whole = static_cast<int>(ratio);
std::cout << ratio << '\n'; std::cout << whole << '\n';}JavaScript: tricky coercion
Section titled “JavaScript: tricky coercion”console.log("10" + 2); // "102"console.log("10" - 2); // 8console.log(true + 1); // 2console.log(false + 1); // 1Python: safe conversion with handling
Section titled “Python: safe conversion with handling”raw = "42"
try: value = int(raw) print(value + 8)except ValueError: print("invalid input")Classic beginner mistakes
Section titled “Classic beginner mistakes”- using strings for everything
- comparing
"10"with10 - using
floatfor money - thinking
charhas no numeric value - converting without validation
- mixing missing value with zero
- ignoring the limits of a type
Signs your modeling is weak
Section titled “Signs your modeling is weak”- the same field changes type across layers
- you keep converting values repeatedly
- the system is full of defensive conditionals with no clarity
- bugs show up in sorting, filtering, calculation, and serialization
Exercises that are actually worth doing
Section titled “Exercises that are actually worth doing”- Convert
13to binary by hand. - Convert
0.625to binary by hand. - Show in code that
'A'equals65. - Model an order using cents instead of float.
- Perform safe string-to-integer parsing in C, C++, JavaScript, and Python.
- Compare
0.1 + 0.2with0.3and explain the result.
Strong data-type checklist
Section titled “Strong data-type checklist”- Do you understand bits, bytes, and binary representation?
- Do you know the difference between integer, float, char, string, and bool?
- Do you know that a character is also a number?
- Do you understand the basics of two’s complement?
- Do you know why float fails for money?
- Do you know when explicit cast is appropriate?
- Do you validate invalid input before converting?
If you check these boxes, your foundation already moves past “tutorial level” and into real engineering.
Next actions
Section titled “Next actions”- Open the ASCII Table now
- Then continue to Data Structures
- If you want stronger reasoning, move on to Programming Logic