What is uintptr_t
?
uintptr_t
is an unsigned integer type defined in the <stdint.h>
header of the C standard library. It is designed to be large enough to hold any pointer value. This makes it an essential type for scenarios where pointers need to be manipulated as integers.
This type is guaranteed to be large enough to hold any pointer value, making it an essential tool for portable and platform-independent pointer manipulation.
History
C99 Standard:
- The C99 standard, published in 1999, introduced
stdint.h
, which defines fixed-width integer types. - Within
stdint.h
, the typesuintptr_t
andintptr_t
were introduced.uintptr
is an unsigned integer type capable of holding any integer value.
Why use uintptr_t
?
1 Portability:
- Different architectures (e.g., 32-bit vs. 64-bit) have different pointer sizes. Using
uintptr_t
ensures that your code can handle pointers correctly regardless of the underlying architecture.
Its Size
The size of uintptr_t
varies depending on the architecture of the system because it is designed to be able to hold any pointer value.
32-bit Architectures:
- 32-bit x86 (IA-32)
- Size of
uintptr_t
: 4 bytes (32 bits) - Pointers on 32-bit x86 architectures are 32 bits, so
uintptr_t
is also 32 bits to accommodate this.
- Size of
- ARM (32-bit)
- Size of
uintptr_t
: 4 bytes (32 bits) - Similar to x86, pointers are 32 bits in a 32-bit ARM architecture.
- Size of
64-bit Architectures:
- 64-bit x86 (x86_64 or AMD64)
- Size of
uintptr_t
: 8 bytes (64 bits) - Pointers on 64-bit x86 architectures are 64 bits, so
uintptr_t
is also 64 bits to accommodate this.
- Size of
- ARM (64-bit, ARM64 or AArch64)
- Size of
uintptr_t
: 8 bytes (64 bits) - Similar to x86_64, pointers are 64 bits in a 64-bit ARM architecture.
- Size of
Other Architectures:
- 64-bit PowerPC (PPC64)
- Size of
uintptr_t
: 8 bytes (64 bits) - Pointers in 64-bit PowerPC architectures are 64 bits, so
uintptr_t
follows suit.
- Size of
- 64-bit SPARC (SPARC64)
- Size of
uintptr_t
: 8 bytes (64 bits) - Pointers in 64-bit SPARC architectures are also 64 bits.
- Size of
Summary Table
Architecture | Size of uintptr_t |
---|
32-bit x86 | 4 bytes (32 bits) |
32-bit ARM | 4 bytes (32 bits) |
64-bit x86_64 | 8 bytes (64 bits) |
64-bit ARM64 | 8 bytes (64 bits) |
64-bit PPC64 | 8 bytes (64 bits) |
64-bit SPARC64 | 8 bytes (64 bits) |
Explanation:
- The size of
uintptr_t
is directly related to the size of pointers on the given architecture. - On 32-bit architectures, pointers are 32 bits long, making
uintptr_t
32 bits. - On 64-bit architectures, pointers are 64 bits long, making
uintptr_t
64 bits.
Implementation
#define NULL ((void *)0UL)
typedef unsigned long uintptr_t;
typedef long size_t;
Explanation:
uintptr_t
is defined asunsigned long
.size_t
is defined aslong
.
Size Determination by Architecture:
The size of unsigned long
and long
can vary depending on the architecture and the platform-specific implementation.
32-bit Architectures:
- On most 32-bit systems (e.g., 32-bit x86):
unsigned long
: 4 bytes (32 bits)long
: 4 bytes (32 bits)
Thus, on a 32-bit architecture:
uintptr_t
(defined asunsigned long
) will be 4 bytes.size_t
(defined aslong
) will be 4 bytes.
64-bit Architectures:
- On most 64-bit systems (e.g., 64-bit x86_64, 64-bit ARM):
unsigned long
: 8 bytes (64 bits)long
: 8 bytes (64 bits)
Thus, on a 64-bit architecture:
uintptr_t
(defined asunsigned long
) will be 8 bytes.size_t
(defined aslong
) will be 8 bytes.
Summary Table
Architecture | Size of uintptr_t | Size of size_t |
---|
32-bit | 4 bytes (32 bits) | 4 bytes (32 bits) |
64-bit | 8 bytes (64 bits) | 8 bytes (64 bits) |
Why cant we use unsigned int
for uintptr_t
and size_t
:
Because:
32-bit Systems
- On most 32-bit systems:
int
is typically 4 bytes (32 bits).long
is typically 4 bytes (32 bits).
In this case, both unsigned int
and unsigned long
would be 4 bytes, so theoretically, using unsigned int
for uintptr_t
and size_t
would work fine.
64-bit Systems
- On most 64-bit systems:
int
is typically still 4 bytes (32 bits).long
is typically 8 bytes (64 bits).
In this case, unsigned int
would be 4 bytes, while unsigned long
would be 8 bytes. Since pointers on 64-bit systems are 64 bits, unsigned int
would not be able to hold a pointer value correctly. Thus, using unsigned int
for uintptr_t
and size_t
would fail to represent pointer values on 64-bit architectures.
Why unsigned long
is Used:
unsigned long
is chosen because it typically matches the size of pointers on most architectures:- 32-bit systems:
unsigned long
is 4 bytes, matching 32-bit pointers. - 64-bit systems:
unsigned long
is 8 bytes, matching 64-bit pointers.
- 32-bit systems:
This ensures that uintptr_t
can hold any pointer value, making it safe and portable across different architectures.