Integer Boundaries: C23 vs Java SE 25 vs Python 3.14

By FreePare Team · Mon Jul 27 2026 · 9 min read

Integer Boundaries: C23 vs Java SE 25 vs Python 3.14

A practical guide to integer boundaries in C23, Java SE 25, and Python 3.14

Integers look harmless. They arrive wearing sensible names such as countpriceindex, and timeout. Then one of them reaches a boundary, flips sign, refuses to fit, or quietly changes type.

That is when the tiny accountant inside the CPU throws the ledger out of the window.

This article replaces scary folklore with code you can run. We will compare language guarantees, implementation details, and failure modes without pretending that C, Java, and Python use the same rules.

What this article covers

1. Three languages, three contracts

The number 42 is mathematical. The expression that stores it is a programming-language contract.

C23

C defines minimum ranges for its standard integer types. It does not promise that int is exactly 32 bits on every implementation. If a format or protocol needs an exact width, use the optional exact-width types when the implementation provides them:

#include <stdint.h>

int32_t temperature_milli_celsius;
uint64_t packet_sequence;

Before assuming that an exact-width type exists, portable library code can check:

#include <stdint.h>

#ifdef INT32_MAX
/* int32_t exists on this implementation. */
#endif

int32_t is especially useful for an in-memory value with a required width. It does not automatically solve byte order or serialization. A 32-bit value still needs an agreed network/file encoding.

Java SE 25

Java gives its integral primitives fixed widths:

TypeWidthMinimumMaximum
byte8-128127
short16-32,76832,767
int32-2,147,483,6482,147,483,647
long64-9,223,372,036,854,775,8089,223,372,036,854,775,807

Java also has char, an unsigned 16-bit UTF-16 code unit. It is not a small signed integer and should not be used as one.

Python 3.14

Python's int represents integers of arbitrary size:

small = 42
large = 2**10_000

print(small.bit_length())  # 6
print(large.bit_length())  # 10001

There is no fixed INT_MAX for Python integers. The practical limits are available memory, execution time, and safeguards on certain conversions such as extremely long integer-to-string operations.

How those values are stored is an implementation matter. Statements about "30-bit digits" describe common CPython builds, not the Python language contract.

2. The promotion trap: a short may not do short arithmetic

Conversion is the neighbouring question and it has its own rules: "Copy, Cast, or Alias?" covers what a cast does to the value, while this article covers what the type can hold.

Consider this C program:

#include <limits.h>
#include <stdio.h>

int main(void) {
    short raw = SHRT_MIN;
    int promoted_result = raw * 2;
    short narrowed_result = raw * 2;

    printf("SHRT_MIN:        %d\n", SHRT_MIN);
    printf("promoted result: %d\n", promoted_result);
    printf("narrowed result: %d\n", narrowed_result);
}

On a common implementation with a 32-bit intraw is promoted to int before multiplication. The mathematical result, -65536, fits in int, so the multiplication itself does not overflow.

The interesting operation is the later conversion back to short. Because -65536 does not fit, converting it to a signed short produces an implementation-defined result or raises an implementation-defined signal.

That distinction matters:

Compile with warnings and sanitizers:

gcc -std=c2x -O2 -Wall -Wextra -Wconversion \
    -fsanitize=undefined integer_promotion.c

Always state the compiler version, target architecture, flags, and type widths when publishing a result.

3. Overflow: chaos, wraparound, or a larger integer

C signed overflow

#include <limits.h>

int x = INT_MAX;
x = x + 1; /* Undefined behavior. */

The C abstract machine does not define a wrapped result for signed overflow. Optimizers may assume that a valid program does not perform it.

This is why the following is not a reliable overflow check:

if (x + 1 < x) {
    /* Too late: evaluating x + 1 may already be undefined. */
}

Check before calculating:

#include <limits.h>
#include <stdbool.h>

bool add_int(int a, int b, int *out) {
    if ((b > 0 && a > INT_MAX - b) ||
        (b < 0 && a < INT_MIN - b)) {
        return false;
    }

    *out = a + b;
    return true;
}

GCC and Clang also provide checked-arithmetic built-ins:

int result;
if (__builtin_add_overflow(a, b, &result)) {
    /* Handle overflow. */
}

That built-in is useful, but it is a compiler extension rather than portable ISO C.

C unsigned wraparound

Unsigned arithmetic is reduced modulo \(2^N\), where N is the width of the type:

#include <limits.h>
#include <stdio.h>

int main(void) {
    unsigned int x = UINT_MAX;
    printf("%u\n", x + 1U); /* 0 */
}

Defined wraparound is useful for bit masks, hash functions, and ring counters. It is dangerous when a wrapped value represents an allocation size, security boundary, or account balance.

Also watch mixed signed/unsigned comparisons:

printf("%d\n", -1 < 0U); /* Prints 0 on common implementations. */

The usual arithmetic conversions convert -1 to an unsigned value before comparison.

Java wraparound and checked arithmetic

Java defines wraparound for int and long arithmetic:

public class IntegerBoundaryLab {
    public static void main(String[] args) {
        int wrapped = Integer.MAX_VALUE + 1;
        System.out.println(wrapped); // -2147483648

        try {
            int checked = Math.addExact(Integer.MAX_VALUE, 1);
            System.out.println(checked);
        } catch (ArithmeticException ex) {
            System.out.println("Overflow detected");
        }
    }
}

Useful checked methods include:

Use them when a wrapped result would violate the domain model. Do not assume they are "too slow" without measuring the real workload.

Python grows

x = 2**63 - 1
x += 1

print(x)  # 9223372036854775808

Python does not wrap the value. It allocates enough storage to represent the result. Arithmetic on larger values generally requires more work, but there is no magical single boundary where a program suddenly becomes slow. Benchmark the actual operand sizes and operations.

4. The smallest signed integer is a tiny trapdoor

For a two's-complement 32-bit signed integer, the range is asymmetric:

minimum = -2,147,483,648
maximum =  2,147,483,647

The positive counterpart of the minimum does not fit.

C

For int, both of these can be undefined when the result is not representable:

abs(INT_MIN);
INT_MIN / -1;

Java

Java preserves its wraparound rules:

System.out.println(Math.abs(Integer.MIN_VALUE));
// -2147483648

System.out.println(Integer.MIN_VALUE / -1);
// -2147483648

For checked negation:

Math.negateExact(Integer.MIN_VALUE); // ArithmeticException

Python

Python produces the mathematical result:

x = -(2**31)
print(abs(x))  # 2147483648
print(x // -1) # 2147483648

5. Shifts have rules too

In Java, only part of the right operand is used as the shift distance:

System.out.println(1 << 32); // 1, because 32 is masked to 0 for int

For an int, Java uses the low five bits of the distance. For a long, it uses the low six.

Python permits arbitrarily large non-negative shift counts:

print(1 << 100)

A negative Python shift count raises ValueError.

C is stricter and more dangerous. A negative shift count or one greater than or equal to the promoted left operand's width is undefined. Left-shifting a signed value can also become undefined when the result is not representable. Use unsigned types for deliberate bit manipulation and validate the count.

6. A boundary-first test table

For every fixed-width signed operation, test at least:

CaseWhy
0Additive identity and division boundary
1Smallest positive value
-1Sign conversion and division edge
MAXPositive overflow boundary
MAX - 1One operation before overflow
MINNegation, absolute-value, and division trap
MIN + 1One operation above the lower boundary
Powers of twoShift and bit-mask behavior
Values around target-width limitsNarrowing conversions
Mixed signed/unsigned valuesC conversion surprises

A test is stronger when it states the expected language-level result:

7. Picking the right representation

Counters

Use a type whose maximum cannot be reached during the counter's lifetime, and define rollover behavior explicitly.

Money

Prefer integer minor units such as paise or cents when the scale is fixed. Check multiplication and aggregation. Arbitrary precision does not automatically solve rounding rules or currency-scale errors.

File and network formats

Use declared widths and byte order. Validate before converting into a smaller local type.

Array and allocation sizes

Use size_t in C for object sizes, but check multiplication:

if (count > SIZE_MAX / sizeof(*items)) {
    /* Allocation size would overflow. */
}

Database values

Do not assume the database column and application type share a range. Validate values at the boundary where they cross systems.

Try it yourself

1. Run the C promotion example with -O0 and -O2. Record sizeof(short)sizeof(int), and the compiler target.

2. Add INT_MAX and 1 using unchecked and checked code in all three languages.

3. Test MIN / -1abs(MIN), and negation.

4. Compare Java's (int) 1e20, C's conversion of an out-of-range double, and Python's int(1e20).

5. Serialize 0x01020304 and inspect the byte order rather than guessing it.

For the layer below this one — where a value becomes bytes, and where allocation arithmetic can overflow before a single byte is written — see Bytes, Bounds, and Unicode Gremlins.

Exit test

You understand this topic when you can classify an integer operation before executing it:

1. Which types do the operands have after promotion?

2. Is the mathematical result representable?

3. Does the language define wrapping, checking, conversion, or undefined behavior?

4. Is an implementation detail being mistaken for a language guarantee?

5. What boundary tests prove the code's intended policy?

Final byte

Integers are not villains. They are extremely literal coworkers.

Tell them the width, the range, the overflow policy, and the conversion rules, and they will behave perfectly. Leave those details implicit, and they may still behave perfectly - just according to a contract you never read.

Tags: how-to-study-better, smart-study-tips, technical-interview-preparation, coding-interview-tips, coding-fundamentals, study-tips-for-students, computer-science-fundamentals, programming-fundamentals