Issue 1133: *_MIN, *_MAX, and *_WIDTH macros as integer constant expressions

Authors: Jay Ghiron
Date: 2026-11-12
Submitted against: C23
Status: Open
Cross-references: 1056

The values given subsequently shall be replaced by constant expressions suitable for use in conditional expression inclusion preprocessing directives. Their implementation-defined values shall be equal or greater to those shown.

For all unsigned integer types for which <limits.h> or <stdint.h> define a macro with suffix _WIDTH holding its width N, there is a macro with suffix _MAX holding the maximal value 2N − 1 that is representable by the type and that has the same type as would an expression that is an object of the corresponding type converted according to the integer promotions. If the value is in the range of the type uintmax_t (7.22.2.6) the macro is suitable for use in conditional expression inclusion preprocessing directives.

For all signed integer types for which <limits.h> or <stdint.h> define a macro with suffix _WIDTH holding its width N, there are macros with suffix _MIN and _MAX holding the minimal and maximal values −2N − 1 and 2N − 1 − 1 that are representable by the type and that have the same type as would an expression that is an object of the corresponding type converted according to the integer promotions. If the values are in the range of the type intmax_t (7.22.2.6) the macros are suitable for use in conditional expression inclusion preprocessing directives.

If an object of type char can hold negative values, the value of CHAR_MIN shall be the same as that of SCHAR_MIN and the value of CHAR_MAX shall be the same as that of SCHAR_MAX. Otherwise, the value of CHAR_MIN shall be 0 and the value of CHAR_MAX shall be the same as that of UCHAR_MAX (see 6.2.5.).

(C23 5.3.5.3.2 "Characteristics of integer types <limits.h>".)

There does not appear to be anything that requires the *_MIN and *_MAX macros derived from the *_WIDTH macros to expand to integer constant expressions, though the requirements for some macros to be usable in conditional expression inclusion preprocessing directives could be interpreted as requiring integer constant expressions.

There also does not appear to be anything that requires the signed *_WIDTH macros in <limits.h> and CHAR_WIDTH to expand to integer constant expressions, this section only defines their values.

The following are a few asides that I noticed when making this issue:

  1. The start of this section only says constant expressions instead of integer constant expressions. The suggested correction clarifies this. There are several other parts of the standard which do not specify this: C23 5.3.5.3.3 paragraph 21, C23 5.3.5.3.4 paragraph 6, C23 7.17.1 paragraph 4, C23 7.22.3.1 paragraph 2, C23 7.22.4.1 paragraph 2, C23 E.1 paragraph 1, and C23 E.2 paragraph 3. Since there is wording to require suitability for use in conditional expression inclusion preprocessing directives it perhaps could be interpreted as already being required. There is one instance of "integer constant expression suitable for use in conditional expression inclusion preprocessing directives": C23 F.5 paragraph 1. See also issue 1056 for cases of where this distinction matters, not including the cases inside of conditional expression inclusion preprocessing directives.
  2. There are a few instances of "#if preprocessing directives" instead of "conditional expression inclusion preprocessing directives": C23 7.22.3.1 paragraph 2, C23 7.22.4.1 paragraph 2, and C23 E.2 paragraph 3. It would be useful to replace these instances with the more usual wording.
  3. The proposal N3496 added the wording to the working draft "The values of these macros provide the number of bits in the value representation of the type". This seems to be incorrect for signed integer types, since it appears to be referring to the number of value bits which for signed integer types does not include the sign bit. Only unsigned integer types have a proper definition of "value representation", signed integer types and char do not have any definition of "value representation". With N3747 bool is also no longer an unsigned integer type and therefore does not have a definition for its value representation.

Suggested correction

Modify C23 5.3.5.3.2:

The values given subsequently shall be replaced by integer constant expressions suitable for use in conditional expression inclusion preprocessing directives. Their implementation-defined values shall be equal or greater to those shown.

For all unsigned integer types for which <limits.h> or <stdint.h> define a macro with suffix _WIDTH holding its width N, there is a macro with suffix _MAX holding the maximal value 2N − 1 that is representable by the type and that has the same type as would an expression that is an object of the corresponding type converted according to the integer promotions. If the value is in the range of the type uintmax_t (7.22.2.6) the macro is an integer constant expression suitable for use in conditional expression inclusion preprocessing directives; otherwise, the macro is an integer constant expression that need not be suitable for use in conditional expression inclusion preprocessing directives notwithstanding the provisions of 7.1.4.

For all signed integer types for which <limits.h> or <stdint.h> define a macro with suffix _WIDTH holding its width N, there are macros with suffix _MIN and _MAX holding the minimal and maximal values −2N − 1 and 2N − 1 − 1 that are representable by the type and that have the same type as would an expression that is an object of the corresponding type converted according to the integer promotions. If the values are in the range of the type intmax_t (7.22.2.6) the macros are integer constant expressions suitable for use in conditional expression inclusion preprocessing directives; otherwise, the macros are integer constant expressions that need not be suitable for use in conditional expression inclusion preprocessing directives notwithstanding the provisions of 7.1.4.

If an object of type char can hold negative values, the value of CHAR_MIN shall be the same as that of SCHAR_MIN and the value of CHAR_MAX shall be the same as that of SCHAR_MAX. Otherwise, the value of CHAR_MIN shall be 0 and the value of CHAR_MAX shall be the same as that of UCHAR_MAX (see 6.2.5.). Both CHAR_MIN and CHAR_MAX are integer constant expressions suitable for use in conditional expression inclusion preprocessing directives.

Note: This suggested correction does not interfere with the changes made by N3496, if this correction is incorporated into the working draft the changes should be made in the context of the new wording.