The <limits.h> header defines macros for the minimum and maximum values of integer types—char, short, int, long, and their unsigned variants. It also defines CHAR_BIT, the number of bits in a byte. Use these constants to avoid overflow and write portable code.
01
INT_MAX
Largest int.
02
INT_MIN
Smallest int.
03
CHAR_BIT
Bits/byte.
04
UINT_MAX
Max unsigned.
05
LONG_MAX
Long range.
06
Portable
Use macros.
Fundamentals
Definition and Usage
Every integer type has a finite range. Adding 1 to INT_MAX overflows; subtracting 1 from INT_MIN underflows. The C standard does not fix how many bits an int has—that depends on the compiler and platform—but <limits.h> always tells you the limits for your build.
Macros use a naming pattern: TYPE_MAX and TYPE_MIN for signed types, and UTYPE_MAX for unsigned types (minimum is always 0). Prefixes include SCHAR_, SHRT_, INT_, LONG_, and LLONG_ (C99).
💡
Beginner Tip
The old reference showed #define INT_MAX 2147483647 as if you write those lines yourself. You include<limits.h> and read the macros—never redefine them in your program.
Foundation
📝 Syntax
Include the header:
C
#include <limits.h>
Character and byte
CHAR_BIT — bits in a char (typically 8).
SCHAR_MIN / SCHAR_MAX — range of signed char.
UCHAR_MAX — maximum unsigned char (often 255).
CHAR_MIN / CHAR_MAX — range of plain char (signedness implementation-defined).
Signed integer types
SHRT_MIN / SHRT_MAX — short.
INT_MIN / INT_MAX — int.
LONG_MIN / LONG_MAX — long.
LLONG_MIN / LLONG_MAX — long long (C99).
Unsigned integer types
USHRT_MAX, UINT_MAX, ULONG_MAX, ULLONG_MAX.
Unsigned minimum is always 0 (no UINT_MIN macro).
Typical values (32-bit int platform)
C
/* Examples only — use macros from limits.h, not literals */
CHAR_BIT /* often 8 */
SCHAR_MIN /* often -128 */
SCHAR_MAX /* often 127 */
UCHAR_MAX /* often 255 */
INT_MIN /* often -2147483648 */
INT_MAX /* often 2147483647 */
UINT_MAX /* often 4294967295 */
Headers and linking
#include <limits.h> — macros only, no link flag.
For fixed-width types, also see <stdint.h> (INT32_MAX, etc.).
For floating limits, see <float.h>.
Compile: gcc program.c -std=c11 -o program
Cheat Sheet
⚡ Quick Reference
Macro
Type
Typical role
CHAR_BIT
char
Bits per byte (usually 8)
INT_MAX
int
Upper bound for int
INT_MIN
int
Lower bound for int
UINT_MAX
unsigned int
Max unsigned int
LONG_MAX
long
Platform-dependent (32 or 64 bit)
UCHAR_MAX
unsigned char
0–255 on 8-bit char systems
Overflow
if (a > INT_MAX - b)
Safe add check
Bits
sizeof(int)*CHAR_BIT
int bit width
Print
printf("%u", UINT_MAX)
Unsigned format
Validate
x >= INT_MIN && x <= INT_MAX
Range check
Hands-On
Examples Gallery
Compile with gcc file.c -std=c11 -o out. Sample output matches typical GCC on a 64-bit system with 32-bit int and 64-bit long.
📚 Getting Started
See what your compiler reports for each integer type.
Example 1 — Print Integer Type Ranges
From the reference, with complete output and correct printf formats for unsigned types.
C
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("CHAR_BIT = %d\n\n", CHAR_BIT);
printf("signed char: %d to %d\n", SCHAR_MIN, SCHAR_MAX);
printf("unsigned char: 0 to %u\n", UCHAR_MAX);
printf("short: %d to %d\n", SHRT_MIN, SHRT_MAX);
printf("unsigned short:0 to %u\n", USHRT_MAX);
printf("int: %d to %d\n", INT_MIN, INT_MAX);
printf("unsigned int: 0 to %u\n", UINT_MAX);
printf("long: %ld to %ld\n", LONG_MIN, LONG_MAX);
printf("unsigned long: 0 to %lu\n", ULONG_MAX);
return 0;
}
📤 Output (typical GCC x86-64):
CHAR_BIT = 8
signed char: -128 to 127
unsigned char: 0 to 255
short: -32768 to 32767
unsigned short:0 to 65535
int: -2147483648 to 2147483647
unsigned int: 0 to 4294967295
long: -9223372036854775808 to 9223372036854775807
unsigned long: 0 to 18446744073709551615
How It Works
The old reference output showed only the last three lines. Here every type is printed. Use %u / %lu for unsigned macros so values display correctly.
Example 2 — Safe Addition Before Overflow
Check whether a + b would exceed INT_MAX before adding.
C
#include <limits.h>
#include <stdio.h>
int safe_add(int a, int b, int *out) {
if (b > 0 && a > INT_MAX - b) {
return -1; /* overflow */
}
if (b < 0 && a < INT_MIN - b) {
return -1; /* underflow */
}
*out = a + b;
return 0;
}
int main(void) {
int result;
if (safe_add(INT_MAX, 1, &result) != 0) {
printf("Overflow avoided: INT_MAX + 1 does not fit in int\n");
} else {
printf("Result: %d\n", result);
}
return 0;
}
📤 Output:
Overflow avoided: INT_MAX + 1 does not fit in int
How It Works
Instead of hard-coding 2147483647, use INT_MAX. The check a > INT_MAX - b detects overflow before it happens. Production code on GCC may use built-ins like __builtin_add_overflow; this pattern teaches the idea.
📈 Practical Patterns
Measure types, validate input, and compare sizes.
Example 3 — CHAR_BIT and sizeof
Compute how many bits each integer type uses on your platform.
CHAR_BIT converts byte counts from sizeof into bit widths. This explains why INT_MAX is about 2×109 on a 32-bit int system.
Example 4 — Validate a Value Fits in int
Reject numbers outside INT_MIN…INT_MAX before storing in an int.
C
#include <limits.h>
#include <stdio.h>
int fits_in_int(long value) {
return value >= INT_MIN && value <= INT_MAX;
}
int main(void) {
long candidates[] = { 100L, 2147483647L, 3000000000L };
for (size_t i = 0; i < 3; i++) {
long v = candidates[i];
printf("%ld: %s\n", v,
fits_in_int(v) ? "fits in int" : "too large for int");
}
return 0;
}
📤 Output:
100: fits in int
2147483647: fits in int
3000000000: too large for int
How It Works
3000000000 exceeds INT_MAX (2147483647 on typical systems). Comparing against macros keeps the check portable if int size changes.
Example 5 — Compare limits.h with sizeof
See how macro ranges relate to type sizes—and why you need both headers for different jobs.
limits.h says:
INT_MAX = 2147483647
UINT_MAX = 4294967295
sizeof says:
int = 4 bytes
unsigned int = 4 bytes
Rule of thumb: 4-byte int holds roughly 10 decimal digits.
How It Works
limits.h gives exact min/max values; sizeof gives storage size. For fixed 32-bit integers regardless of platform, use <stdint.h> and int32_t instead.
Applications
🚀 Common Use Cases
Overflow checks — validate sums, products, and array index math.
Input validation — ensure parsed numbers fit the target type.
Buffer sizing — use UCHAR_MAX + 1 (256) for byte tables when char is 8 bits.
Portable constants — replace magic numbers in algorithms.
Serialization — pick the narrowest type that fits a value range.
Embedded systems — confirm int width before porting desktop code.
🧠 How limits.h Works
1
Include limits.h
Compiler provides macros matching its integer model.
Setup
2
Read TYPE_MAX/MIN
Constants expand at compile time—no runtime lookup.
Constants
3
Guard operations
Compare inputs and intermediate results against limits.
Protect
=
💬
Portable integer code
Same source adapts when long is 32 or 64 bits.
Important
📝 Notes
Macro values are implementation-defined—never hard-code 2147483647.
char may be signed or unsigned; use signed char / unsigned char when sign matters.
Unsigned overflow wraps modulo UTYPE_MAX + 1; signed overflow is undefined behavior.
INT_MIN often has no positive counterpart (e.g. -2147483648).
C99 adds LLONG_* macros for long long.
For floating-point limits, use <float.h>, not limits.h.
Performance
⚡ Optimization
Limit macros compile to constants—zero runtime cost. Choose the smallest type that fits your data (unsigned char for 0–255) to save memory in large arrays. Overflow checks add branches; keep them on untrusted input paths, not every inner-loop increment.
Wrap Up
Conclusion
<limits.h> is the portable way to learn how big your integer types are on any platform. Use INT_MAX, INT_MIN, UINT_MAX, and CHAR_BIT for range checks, validation, and clear code.
Pair it with <stdint.h> when you need exact bit widths, and <float.h> for floating-point limits.
Check overflow before arithmetic on untrusted data
Use signed char when you need negative bytes
Print limits once on a new platform during porting
❌ Don’t
Redefine #define INT_MAX in your own code
Assume int is always 32 bits
Print UINT_MAX with %d
Confuse CHAR_MAX with SCHAR_MAX blindly
Rely on signed integer overflow “wrapping” (undefined in C)
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about limits.h
Integer limits in C, explained simply.
5
Core concepts
💬01
INT_MAX
Top int.
Range
📚02
CHAR_BIT
Bits/byte.
Size
📈03
UINT_MAX
Unsigned.
Format %u
📄04
Overflow
Check first.
Safety
🌐05
Portable
Use macros.
Platform
❓ Frequently Asked Questions
limits.h defines implementation-specific macros for integer type limits: minimum and maximum values for char, short, int, long, and their unsigned forms, plus CHAR_BIT (bits per char). Use these macros instead of hard-coding numbers like 2147483647.
SCHAR_MIN and SCHAR_MAX always refer to signed char. CHAR_MIN and CHAR_MAX refer to plain char, which may be signed or unsigned depending on the compiler. On many systems char is signed; on others it is unsigned—use SCHAR_* when you need signed char specifically.
No. An int might be 16 bits on embedded systems and 32 bits on desktops. LONG_MAX differs between 32-bit and 64-bit Windows vs Linux. Always use the macros from limits.h on your target platform.
limits.h names limits after fundamental types (INT_MAX, LONG_MAX). stdint.h provides fixed-width types (int32_t) and matching limits (INT32_MAX). Use limits.h for portable code with int/long; use stdint.h when you need exact bit widths.
CHAR_BIT is the number of bits in a byte (char). It is at least 8 on all standard C implementations and is almost always exactly 8. Use CHAR_BIT with sizeof to compute bit sizes: sizeof(int) * CHAR_BIT.
UINT_MAX is an unsigned int. Printing it with %d treats the value as signed and can show a negative number on some platforms. Match the printf format to the type: %d for signed, %u for unsigned, %lu for unsigned long.
Did you know?
On many 64-bit systems, int is still 32 bits while long is 64 bits—but on Windows LLP64, long remains 32 bits and only long long is 64 bits. That is exactly why limits.h exists: the same source file can print different LONG_MAX values on different targets without changing a single literal in your code.