C stdint.h Header
Fixed-width integer types and their limits
🎯 What is stdint.h?
The stdint.h header provides exact-width integer types like int32_t and uint64_t, ensuring consistent behavior across different platforms and architectures in your C programs.
#include <stdint.h>
#include <stdio.h>
int main() {
int32_t exact32 = 42;
uint64_t exact64 = 1000ULL;
printf("32-bit: %d, 64-bit: %llu\n", exact32, exact64);
return 0;
}
Output:
Key stdint.h Types
Exact Width
Types with exact number of bits
int8_t, int16_t, int32_t
uint8_t, uint16_t, uint32_t
Minimum Width
Types with at least N bits
int_least8_t, int_least16_t
uint_least8_t, uint_least16_t
Fastest Types
Fastest types with at least N bits
int_fast8_t, int_fast16_t
uint_fast8_t, uint_fast16_t
Maximum Types
Largest available integer types
intmax_t, uintmax_t
intptr_t, uintptr_t
🔹 Exact-Width Integer Types
C provides exact-width integer types that guarantee specific bit widths across different platforms and compilers. Types like int8_t, int16_t, int32_t, and int64_t from <stdint.h> ensure your integers have exactly 8, 16, 32, or 64 bits respectively, regardless of the target architecture. This is crucial for portable code, especially in embedded systems, network protocols, and binary file formats where precise data sizes matter. For example, uint32_t counter = 0; guarantees a 32-bit unsigned integer, preventing unexpected overflow behavior or compatibility issues when moving code between 32-bit and 64-bit systems.
#include <stdint.h>
#include <stdio.h>
int main() {
// Exact width types
int8_t byte_val = 127; // Exactly 8 bits
int16_t short_val = 32767; // Exactly 16 bits
int32_t int_val = 2147483647; // Exactly 32 bits
int64_t long_val = 9223372036854775807LL; // Exactly 64 bits
printf("8-bit: %d\n", byte_val);
printf("16-bit: %d\n", short_val);
printf("32-bit: %d\n", int_val);
printf("64-bit: %lld\n", long_val);
// Unsigned versions
uint8_t ubyte = 255;
uint32_t uint_val = 4294967295U;
printf("Unsigned 8-bit: %u\n", ubyte);
printf("Unsigned 32-bit: %u\n", uint_val);
return 0;
}
Output:
16-bit: 32767
32-bit: 2147483647
64-bit: 9223372036854775807
Unsigned 8-bit: 255
Unsigned 32-bit: 4294967295
🔹 Minimum and Fast Types
Minimum-width and fast-width integer types offer flexibility for performance optimization while maintaining portability. The int_least types like int_least16_t guarantee at least the specified number of bits, while int_fast types like int_fast32_t provide the fastest integer type with at least the specified width on the current platform. Using int_fast16_t for loop counters or temporary calculations can improve performance because the compiler selects the most efficient type for your processor architecture. These types balance portability with performance, allowing the compiler to optimize for speed when exact bit widths aren't critical to your algorithm.
#include <stdint.h>
#include <stdio.h>
int main() {
// Minimum width types (at least N bits)
int_least8_t min8 = 100;
int_least16_t min16 = 30000;
// Fastest types (fastest with at least N bits)
int_fast8_t fast8 = 50;
int_fast32_t fast32 = 1000000;
printf("Least 8-bit: %d\n", min8);
printf("Least 16-bit: %d\n", min16);
printf("Fast 8-bit: %d\n", fast8);
printf("Fast 32-bit: %d\n", fast32);
// Show actual sizes
printf("\nActual sizes:\n");
printf("int_least8_t: %zu bytes\n", sizeof(int_least8_t));
printf("int_fast8_t: %zu bytes\n", sizeof(int_fast8_t));
return 0;
}
Output:
Least 16-bit: 30000
Fast 8-bit: 50
Fast 32-bit: 1000000
Actual sizes:
int_least8_t: 1 bytes
int_fast8_t: 1 bytes
🔹 Maximum and Pointer Types
Maximum-width and pointer-sized integer types handle special cases requiring the largest available integers or pointer arithmetic. The intmax_t and uintmax_t types represent the largest integer types supported by your implementation, useful for calculations that need maximum range. Meanwhile, intptr_t and uintptr_t are guaranteed to hold any valid pointer value, making them essential for low-level pointer manipulation and type-punning operations. For example, uintptr_t addr = (uintptr_t)ptr; safely converts a pointer to an integer for bit manipulation or address calculations, which is particularly important in memory allocators, garbage collectors, and systems programming.
#include <stdint.h>
#include <stdio.h>
int main() {
// Maximum width types
intmax_t max_signed = INTMAX_MAX;
uintmax_t max_unsigned = UINTMAX_MAX;
printf("Max signed: %jd\n", max_signed);
printf("Max unsigned: %ju\n", max_unsigned);
// Pointer-sized integers
int value = 42;
intptr_t ptr_as_int = (intptr_t)&value
uintptr_t ptr_as_uint = (uintptr_t)&value
printf("Pointer as signed: %jd\n", (intmax_t)ptr_as_int);
printf("Pointer as unsigned: %ju\n", (uintmax_t)ptr_as_uint);
// Convert back to pointer
int *restored_ptr = (int*)ptr_as_int;
printf("Original value: %d\n", *restored_ptr);
return 0;
}
Output:
Max unsigned: 18446744073709551615
Pointer as signed: 140732920755068
Pointer as unsigned: 140732920755068
Original value: 42