# limits.h **`limits.h`** tells you the integer type limits for the platform you are compiling on. You reach for it when you need to guard against overflow before it happens, or when you want to write code that works correctly regardless of whether `long` is 32 or 64 bits. Writing `2147483647` directly is asking for a silent bug the moment your code moves to a different target. ```c #include INT_MAX // max int (at least 32767; typically 2147483647 on 32-bit) INT_MIN // min int (typically -2147483648) UINT_MAX // max unsigned int LONG_MAX // max long (32-bit on 32-bit systems, 64-bit on 64-bit) LLONG_MAX // max long long: at least 9223372036854775807 CHAR_BIT // bits per char (almost always 8) UCHAR_MAX // max unsigned char (255 on 8-bit char) ``` The right way to check for overflow before it happens: ```c // safe addition: check the headroom first if (a > INT_MAX - b) /* would overflow */; else result = a + b; ``` For fixed-width types (`uint32_t`, etc.), the limits come from `` — `UINT32_MAX`, `INT32_MIN`, and so on. `` covers the standard named types only. ## Practice ```c // compile: gcc -o lim lim.c // run: ./lim try on 32-bit and 64-bit and compare LONG_MAX // description: print integer limits and demonstrate unsigned wraparound #include #include int main(void) { printf("CHAR_BIT = %d\n", CHAR_BIT); printf("INT_MAX = %d\n", INT_MAX); printf("UINT_MAX = %u\n", UINT_MAX); printf("LONG_MAX = %ld\n", LONG_MAX); printf("LLONG_MAX = %lld\n", LLONG_MAX); // unsigned overflow wraps to 0 — this is defined behaviour unsigned int u = UINT_MAX; printf("UINT_MAX + 1 = %u\n", u + 1); // 0 // signed overflow is undefined — check first int a = INT_MAX, b = 1; if (a > INT_MAX - b) puts("INT_MAX + 1 would overflow — caught it"); return 0; } ``` Run this on a 32-bit and a 64-bit machine and compare `LONG_MAX`. On 32-bit Linux it will be 2147483647; on 64-bit it will be 9223372036854775807. That difference is exactly why you should never hardcode the max value of `long`.