Bool
| Type | Size (bytes) | Alignment (bytes) | Range |
|--------|--------------|-------------------|--------|
|
bool
| 1 | 1 | 0 or 1 |
|
b8
| 1 | 1 | 0 or 1 |
|
b16
| 2 | 2 | 0 or 1 |
|
b32
| 4 | 4 | 0 or 1 |
|
b64
| 8 | 8 | 0 or 1 |
[ all bits = value ]
00000000 β false
00000001 β true
0 = false
anything else = treated as true (language-dependent)
Integers
-
intanduinthere are implementation-defined, with not fixed-width.
| Type | Size (bytes) | Alignment (bytes) | Range |
|--------|----------------------------|----------------------------|----------------------------------------------------------------------------------------------|
|
u8
| 1 | 1 | [0 β 255] |
|
u16
| 2 | 2 | [0 β 65,535] |
|
u32
| 4 | 4 | [0 β 4,294,967,295] |
|
u64
| 8 | 8 | [0 β 18,446,744,073,709,551,615] |
|
uint
| 4 (32-bits) or 8 (64-bits) | 4 (32-bits) or 8 (64-bits) | [0 β 4,294,967,295] or [0 β 18,446,744,073,709,551,615] |
|
i8
| 1 | 1 | [-128 β 127] |
|
i16
| 2 | 2 | [-32,768 β 32,767] |
|
i32
| 4 | 4 | [-2,147,483,648 β 2,147,483,647] |
|
i64
| 8 | 8 | [-2^63 β (2^63) - 1] [-9,223,372,036,854,775,808 β 9,223,372,036,854,775,807] |
|
int
| 4 (32-bits) or 8 (64-bits) | 4 (32-bits) or 8 (64-bits) | [-2,147,483,648 β 2,147,483,647] or [-9,223,372,036,854,775,808 β 9,223,372,036,854,775,807] |
Unsigned
[ all bits = value ]
Sign (MSB - most significant bit)
-
All signed integer types (
i8,i16,i32,i64) use twoβs complement with the same layout rule. -
Twoβs complement is just a way to encode negative numbers so that binary addition still works normally.
-
Instead of having a separate βsign + magnitudeβ, the number is stored in a way where:
-
Positive numbers look like normal binary
-
Negative numbers are encoded so that adding works without special rules
-
-
This works because
x + (-x) = 0 (mod 2^N)00000101 (+5) + 11111011 (-5) ----------- 00000000 (carry discarded) -
For any signed integer with N bits:
bit index: N-1 ............ 0 β [ MSB | remaining bits ] -
How to get the negative number :
-
Write +x in binary
-
Invert all bits
-
Add 1
-
-
As an INDIRECT consequence, the MSB (most significant bit) acts as the sign indicator :
-
If MSB = 1 (negative) β fill new bits with 1
-
If MSB = 0 (positive) β fill new bits with 0
-
-
Examples :
00000101 β +5 invert: 11111010 +1: 11111011 11111011 β -5
Pointers
-
"an address value with a specific type".
-
At the memory level, it's just an
uint/uintptr:
| Type | Size (bytes) | Alignment (bytes) | Range |
|--------|----------------------------|----------------------------|---------------------------------------------------------|
|
uint
| 4 (32-bits) or 8 (64-bits) | 4 (32-bits) or 8 (64-bits) | [0 β 4,294,967,295] or [0 β 18,446,744,073,709,551,615] |
Floats (IEEE-754 floating-point)
| Type | Size (bytes) | Alignment (bytes) | Range |
|-------|--------------|-------------------|-------------------------------------|
|
f16
| 2 | 2 | ~Β±6.55Γ10β΄ (β3β4 decimal digits) |
|
f32
| 4 | 4 | ~Β±3.4Γ10Β³βΈ (β7 decimal digits) |
|
f64
| 8 | 8 | ~Β±1.8Γ10Β³β°βΈ (β15β16 decimal digits) |
Final value
-
value = (-1)^sign Γ (1 + mantissa) Γ 2^(exponent - bias)
Bias
-
Bias is a fixed offset added to the real exponent so it can be stored as an unsigned value.
-
Exponent bits are stored without a sign bit. Instead of storing negative exponents directly, IEEE 754 does:
stored_exponent = real_exponent + bias -
So:
-
Negative exponents become small positive numbers
-
Positive exponents become larger numbers
-
Everything fits in an unsigned field
-
Special values
-
Plus Infinite :
-
+β > all finite numbers -
β + 1 = β -
β * 2 = β -
β - β = NaN
| sign | exponent | mantissa |
|------|----------|----------|
| 0 | 11111111 | 000...0 | -
How to get it:
-
1.0f / 0.0f β +β -
huge_value * huge_value β +β // via overflow
-
-
-
Minus Infinite :
-
-β < all finite numbers
| sign | exponent | mantissa |
|------|----------|----------|
| 1 | 11111111 | 000...0 | -
How to get it:
-
-1.0f / 0.0f β -β
-
-
-
NaN :
| sign | exponent | mantissa |
|------|----------|----------|
| x | 11111111 | non-zero |-
There are many NaN bit patterns because mantissa can vary.
-
How to get it:
0.0 / 0.0 β - β sqrt(-1.0) -
Behavior:
NaN == NaN β false NaN != NaN β true NaN < any β false NaN > any β false NaN + 5 = NaN NaN * 10 = NaN
-
-
Subnormals (Denormals) :
-
They represent numbers very close to zero, smaller than the smallest βnormalβ float.
| sign | exponent | mantissa |
|------|----------|----------|
| x | 00000000 | non-zero | -
Normal numbers:
-
value = 1.mantissa Γ 2^(exp - bias)
-
-
Subnormals:
-
value = 0.mantissa Γ 2^(1 - bias)
-
-
No implicit leading 1
-
Reduced precision
-
Without subnormals:
-
smallest normal β 1.175e-38 (f32)
-
next value β 0
-
-
With subnormals:
-
smooth transition to 0
-
(no sudden underflow gap)
-
-
Subnormals are slow on many CPUs:
-
Can be 10β100Γ slower
-
Many systems enable:
-
FTZ (Flush To Zero)
-
DAZ (Denormals Are Zero)
-
-
-
Zero :
+0.0 β -0.0 (bitwise) but +0.0 == -0.0 (comparison)1 / +0.0 = +β 1 / -0.0 = -β
f16
-
half precision, less universally supported in CPUs but common in GPUs and some SIMD extensions.
[ sign | exponent (5 bits) (bias = 15) | mantissa (10 bits) ]
f32
[ sign | exponent (8 bits) (bias = 127) | mantissa (23 bits) ]
-
Example :
-
f32 = 1.00 01111111 00000000000000000000000 [ 00 ][ 00 ][ 80 ][ 3F ]
-
f64
[ sign | exponent (11 bits) (bias = 1023) | mantissa (52 bits) ]
SIMD
-
__m128(128-bit SIMD) -
__m256(256-bit SIMD) -
__m512(512-bit SIMD)