C limits.h Library Reference
Complete reference for limits.h - integer limits, overflow prevention, and portable code with INT_MAX, INT_MIN, etc.
Track Your Progress
Sign in to save your learning progress
What You Will Learn
- ✓Know integer type limits
- ✓Prevent integer overflow
- ✓Write portable code
- ✓Validate input ranges
?Why Use limits.h?
Integer overflow is a common bug source. How do you know if adding 1 to an int will overflow?limits.h tells you the exact boundaries!
Prevent Overflow
Check before adding
Portable Code
Works on all platforms
Input Validation
Check user input
01Introduction to limits.h
What is limits.h?
<limits.h> defines macros that specify the minimum and maximum values for integer types. These values are platform-dependent and help write portable code.
Essential for validation, overflow prevention, and understanding your platform's capabilities.
02Character Type Limits
| Macro | Description | Typical Value |
|---|---|---|
| CHAR_BIT | Bits in a char | 8 |
| CHAR_MIN | Minimum value of char | -128 or 0 |
| CHAR_MAX | Maximum value of char | 127 or 255 |
| SCHAR_MIN | Minimum value of signed char | -128 |
| SCHAR_MAX | Maximum value of signed char | 127 |
| UCHAR_MAX | Maximum value of unsigned char | 255 |
1#include <stdio.h>2#include <limits.h>34int main() {5 printf("=== Character Limits ===\n");6 printf("CHAR_BIT: %d bits\n", CHAR_BIT);7 printf("CHAR_MIN: %d\n", CHAR_MIN);8 printf("CHAR_MAX: %d\n", CHAR_MAX);9 printf("SCHAR_MIN: %d\n", SCHAR_MIN);10 printf("SCHAR_MAX: %d\n", SCHAR_MAX);11 printf("UCHAR_MAX: %u\n", UCHAR_MAX);12 13 return 0;14}1516/* Output (typical):17=== Character Limits ===18CHAR_BIT: 8 bits19CHAR_MIN: -12820CHAR_MAX: 12721SCHAR_MIN: -12822SCHAR_MAX: 12723UCHAR_MAX: 25524*/03Short Integer Limits
| Macro | Description | Typical Value |
|---|---|---|
| SHRT_MIN | Minimum value of short | -32768 |
| SHRT_MAX | Maximum value of short | 32767 |
| USHRT_MAX | Maximum value of unsigned short | 65535 |
1#include <stdio.h>2#include <limits.h>34int main() {5 printf("=== Short Limits ===\n");6 printf("SHRT_MIN: %d\n", SHRT_MIN);7 printf("SHRT_MAX: %d\n", SHRT_MAX);8 printf("USHRT_MAX: %u\n", USHRT_MAX);9 10 // Demonstration of overflow11 short s = SHRT_MAX;12 printf("\nshort s = SHRT_MAX = %d\n", s);13 s = s + 1; // Overflow! (undefined behavior for signed)14 printf("s + 1 = %d (overflow!)\n", s);15 16 return 0;17}1819/* Output:20=== Short Limits ===21SHRT_MIN: -3276822SHRT_MAX: 3276723USHRT_MAX: 655352425short s = SHRT_MAX = 3276726s + 1 = -32768 (overflow!)27*/04Integer Limits
| Macro | Description | Typical Value (32-bit) |
|---|---|---|
| INT_MIN | Minimum value of int | -2,147,483,648 |
| INT_MAX | Maximum value of int | 2,147,483,647 |
| UINT_MAX | Maximum value of unsigned int | 4,294,967,295 |
1#include <stdio.h>2#include <limits.h>34int main() {5 printf("=== Integer Limits ===\n");6 printf("INT_MIN: %d\n", INT_MIN);7 printf("INT_MAX: %d\n", INT_MAX);8 printf("UINT_MAX: %u\n", UINT_MAX);9 10 // Size of int11 printf("\nSize of int: %zu bytes\n", sizeof(int));12 printf("Bits in int: %zu\n", sizeof(int) * CHAR_BIT);13 14 return 0;15}1617/* Output:18=== Integer Limits ===19INT_MIN: -214748364820INT_MAX: 214748364721UINT_MAX: 42949672952223Size of int: 4 bytes24Bits in int: 3225*/05Long Integer Limits
| Macro | Description | Typical Value |
|---|---|---|
| LONG_MIN | Minimum value of long | -2^31 or -2^63 |
| LONG_MAX | Maximum value of long | 2^31-1 or 2^63-1 |
| ULONG_MAX | Maximum value of unsigned long | 2^32-1 or 2^64-1 |
| LLONG_MIN | Minimum value of long long | -9,223,372,036,854,775,808 |
| LLONG_MAX | Maximum value of long long | 9,223,372,036,854,775,807 |
| ULLONG_MAX | Maximum value of unsigned long long | 18,446,744,073,709,551,615 |
1#include <stdio.h>2#include <limits.h>34int main() {5 printf("=== Long Limits ===\n");6 printf("LONG_MIN: %ld\n", LONG_MIN);7 printf("LONG_MAX: %ld\n", LONG_MAX);8 printf("ULONG_MAX: %lu\n", ULONG_MAX);9 10 printf("\n=== Long Long Limits ===\n");11 printf("LLONG_MIN: %lld\n", LLONG_MIN);12 printf("LLONG_MAX: %lld\n", LLONG_MAX);13 printf("ULLONG_MAX: %llu\n", ULLONG_MAX);14 15 printf("\nSize of long: %zu bytes\n", sizeof(long));16 printf("Size of long long: %zu bytes\n", sizeof(long long));17 18 return 0;19}2021/* Output (64-bit system):22=== Long Limits ===23LONG_MIN: -922337203685477580824LONG_MAX: 922337203685477580725ULONG_MAX: 184467440737095516152627=== Long Long Limits ===28LLONG_MIN: -922337203685477580829LLONG_MAX: 922337203685477580730ULLONG_MAX: 184467440737095516153132Size of long: 8 bytes33Size of long long: 8 bytes34*/06Practical Uses
Overflow Prevention
1#include <stdio.h>2#include <limits.h>3#include <stdbool.h>45// Safe addition that checks for overflow6bool safe_add(int a, int b, int *result) {7 // Check for overflow before adding8 if (b > 0 && a > INT_MAX - b) {9 return false; // Would overflow10 }11 if (b < 0 && a < INT_MIN - b) {12 return false; // Would underflow13 }14 *result = a + b;15 return true;16}1718// Safe multiplication19bool safe_multiply(int a, int b, int *result) {20 if (a == 0 || b == 0) {21 *result = 0;22 return true;23 }24 25 if (a > 0 && b > 0 && a > INT_MAX / b) return false;26 if (a > 0 && b < 0 && b < INT_MIN / a) return false;27 if (a < 0 && b > 0 && a < INT_MIN / b) return false;28 if (a < 0 && b < 0 && a < INT_MAX / b) return false;29 30 *result = a * b;31 return true;32}3334int main() {35 int result;36 37 if (safe_add(INT_MAX, 1, &result)) {38 printf("INT_MAX + 1 = %d\n", result);39 } else {40 printf("INT_MAX + 1 would overflow!\n");41 }42 43 if (safe_add(100, 200, &result)) {44 printf("100 + 200 = %d\n", result);45 }46 47 if (safe_multiply(INT_MAX, 2, &result)) {48 printf("INT_MAX * 2 = %d\n", result);49 } else {50 printf("INT_MAX * 2 would overflow!\n");51 }52 53 return 0;54}5556/* Output:57INT_MAX + 1 would overflow!58100 + 200 = 30059INT_MAX * 2 would overflow!60*/✓Input Validation
1#include <stdio.h>2#include <limits.h>3#include <stdlib.h>4#include <errno.h>56// Safe string to int conversion7int safe_strtoi(const char *str, int *result) {8 char *endptr;9 errno = 0;10 11 long val = strtol(str, &endptr, 10);12 13 // Check for conversion errors14 if (errno == ERANGE) {15 return -1; // Out of range16 }17 if (endptr == str) {18 return -2; // No digits found19 }20 if (*endptr != '\0') {21 return -3; // Extra characters after number22 }23 24 // Check if value fits in int25 if (val < INT_MIN || val > INT_MAX) {26 return -1; // Out of int range27 }28 29 *result = (int)val;30 return 0; // Success31}3233int main() {34 const char *tests[] = {"42", "-100", "99999999999", "abc", "123abc"};35 int result;36 37 for (int i = 0; i < 5; i++) {38 int status = safe_strtoi(tests[i], &result);39 if (status == 0) {40 printf("'%s' -> %d\n", tests[i], result);41 } else {42 printf("'%s' -> Error (code %d)\n", tests[i], status);43 }44 }45 46 return 0;47}4849/* Output:50'42' -> 4251'-100' -> -10052'99999999999' -> Error (code -1)53'abc' -> Error (code -2)54'123abc' -> Error (code -3)55*/Finding Min/Max with Sentinel
1#include <stdio.h>2#include <limits.h>34int main() {5 int numbers[] = {45, -23, 89, 12, -67, 34, 0};6 int n = sizeof(numbers) / sizeof(numbers[0]);7 8 // Initialize with limits as sentinels9 int min = INT_MAX; // Start with largest possible10 int max = INT_MIN; // Start with smallest possible11 12 for (int i = 0; i < n; i++) {13 if (numbers[i] < min) min = numbers[i];14 if (numbers[i] > max) max = numbers[i];15 }16 17 printf("Array: ");18 for (int i = 0; i < n; i++) printf("%d ", numbers[i]);19 printf("\n");20 printf("Minimum: %d\n", min);21 printf("Maximum: %d\n", max);22 23 return 0;24}2526/* Output:27Array: 45 -23 89 12 -67 34 028Minimum: -6729Maximum: 8930*/07Platform Differences
Important:
The size of int and long varies between platforms. Always use limits.h instead of hardcoded values for portable code.
1#include <stdio.h>2#include <limits.h>34int main() {5 printf("=== Platform Information ===\n\n");6 7 printf("Type sizes (in bytes):\n");8 printf(" char: %zu\n", sizeof(char));9 printf(" short: %zu\n", sizeof(short));10 printf(" int: %zu\n", sizeof(int));11 printf(" long: %zu\n", sizeof(long));12 printf(" long long: %zu\n", sizeof(long long));13 14 printf("\nType sizes (in bits):\n");15 printf(" char: %zu\n", sizeof(char) * CHAR_BIT);16 printf(" short: %zu\n", sizeof(short) * CHAR_BIT);17 printf(" int: %zu\n", sizeof(int) * CHAR_BIT);18 printf(" long: %zu\n", sizeof(long) * CHAR_BIT);19 printf(" long long: %zu\n", sizeof(long long) * CHAR_BIT);20 21 return 0;22}2324/* Output varies by platform:252632-bit Windows:27 int: 4 bytes (32 bits)28 long: 4 bytes (32 bits)293064-bit Windows:31 int: 4 bytes (32 bits)32 long: 4 bytes (32 bits) <- Still 32-bit!333464-bit Linux/macOS:35 int: 4 bytes (32 bits)36 long: 8 bytes (64 bits)37*/!Code Pitfalls: Common Mistakes & What to Watch For
Copied code often hardcodes values like 2147483647 or 32767 instead of using INT_MAX or SHRT_MAX, creating non-portable code.
If you search online to "check for integer overflow," it might write if (x > 2147483647) — but this assumes 32-bit int, which isn't guaranteed by the C standard. On 16-bit systems, INT_MAX is 32767. Hardcoded values break on different architectures.
The Trap: Online sources are often trained on code from 64-bit systems and assume modern desktop configurations. They might also forget that long is 4 bytes on Windows but 8 bytes on Linux, leading to subtle bugs when code is ported.
The Reality: Always use limits.h constants like INT_MAX, INT_MIN, CHAR_MAX, LONG_MAX. For exact-size types, use stdint.h with INT32_MAX, UINT64_MAX, etc. This ensures your code is portable and self-documenting.
09Frequently Asked Questions
Q:Why is INT_MAX different on different systems?
A: The C standard only specifies minimum ranges, not exact sizes. int must be at least 16 bits, but is typically 32 bits. That's why you should use limits.h instead of hardcoding values like 2147483647.
Q:How do I detect integer overflow?
A: Check before the operation! For addition: if (a > INT_MAX - b) means overflow. After overflow happens, the behavior is undefined — you can't reliably detect it afterward.
Q:Why is CHAR_MIN sometimes 0 and sometimes -128?
A: Because char can be signed or unsigned depending on the implementation! If you need a guaranteed signed or unsigned char, explicitly usesigned char orunsigned char.
Q:What's CHAR_BIT used for?
A: It tells you how many bits are in a byte (usually 8). Use it to calculate bit sizes:sizeof(int) * CHAR_BIT gives you the number of bits in an int. Essential for portable bit manipulation.
09Complete Reference Table
| Type | Min Macro | Max Macro |
|---|---|---|
| char | CHAR_MIN | CHAR_MAX |
| signed char | SCHAR_MIN | SCHAR_MAX |
| unsigned char | 0 | UCHAR_MAX |
| short | SHRT_MIN | SHRT_MAX |
| unsigned short | 0 | USHRT_MAX |
| int | INT_MIN | INT_MAX |
| unsigned int | 0 | UINT_MAX |
| long | LONG_MIN | LONG_MAX |
| unsigned long | 0 | ULONG_MAX |
| long long | LLONG_MIN | LLONG_MAX |
| unsigned long long | 0 | ULLONG_MAX |
10Best Practices
Use limits.h for Overflow Checking
Before adding to an int, check: if (a > INT_MAX - b). This prevents overflow by ensuring the sum won't exceed the maximum value.
Prefer stdint.h for Fixed Sizes
If you need exactly 32 bits, use int32_t from stdint.h rather than relying on int being 32 bits. limits.h tells you sizes; stdint.h gives you guaranteed sizes.
Print Limits for Debugging
When debugging platform-specific issues, print the limits at program start. This helps identify when code is running on a platform with different type sizes than expected.
stdbool.h Library
Next →stddef.h Library
Test Your Knowledge
Related Tutorials
C stdbool.h Library Reference
Complete reference for stdbool.h - bool type, true/false values, and boolean best practices in C99+.
C stddef.h Library Reference
Complete reference for stddef.h - NULL, size_t, ptrdiff_t, offsetof, and fundamental type definitions.
Data Types & Variables
Learn to store different kinds of data: numbers (int), decimals (float), and characters (char). Understand how much memory each type uses.
Have Feedback?
Found something missing or have ideas to improve this tutorial? Let us know on GitHub!