This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Open status.

2820. Clarify <cstdint> macros

Section: 17.4 [cstdint] Status: Open Submitter: Thomas Köppe Opened: 2016-11-12 Last modified: 2019-03-26

Priority: 3

View all other issues in [cstdint].

View all issues with Open status.

Discussion:

I would like clarification from LWG regarding the various limit macros like INT_8_MIN in <cstdint>, in pursuit of editorial cleanup of this header's synopsis. I have two questions:

  1. At present, macros like INT_8_MIN that correspond to the optional type int8_t are required (unconditionally), whereas the underlying type to which they appertain is only optional. Is this deliberate? Should the macros also be optional?

  2. Is it deliberate that C++ only specifies sized aliases for the sizes 8, 16, 32 and 64, whereas the corresponding C header allows type aliases and macros for arbitrary sizes for implementations that choose to provide extended integer types? Is the C++ wording more restrictive by accident?

[2017-01-27 Telecon]

Priority 3

[2017-03-04, Kona]

C11 ties the macro names to the existence of the types. Marshall to research the second question.

Close 2764 as a duplicate of this issue.

[2017-03-18, Thomas comments and provides wording]

This is as close as I can get to the C wording without resolving part (a) of the issue (whether we deliberately don't allow sized type aliases for sizes other than 8, 16, 32, 64, a departure from C). Once we resolve part (a), we need to revisit <cinttypes> and fix up the synopsis (perhaps to get rid of N) and add similar wording as the one below to make the formatting macros for the fixed-width types optional. For historical interest, this issue is related to LWG 553 and LWG 841.

[2016-07, Toronto Saturday afternoon issues processing]

Status to Open

Previous resolution: [SUPERSEDED]

This wording is relative to N4640.

  1. Append the following content to 17.4.1 [cstdint.syn] p2:

    -2- The header defines all types and macros the same as the C standard library header <stdint.h>. In particular, for each of the fixed-width types (int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t) the type alias and the corresponding limit macros are defined if and only if the implementation provides the corresponding type.

[2017-10-21, Thomas Köppe provides improved wording]

Previous resolution [SUPERSEDED]:

This wording is relative to N4687.

  1. Change 17.4.1 [cstdint.syn], header <cstdint> synopsis, as indicated:

    […]
    using int64_t = signed integer type; // optional
    using intN_t = see below; // optional, see below
    […]
    using int_fast64_t = signed integer type;
    using int_fastN_t = see below; // optional, see below
    […]
    using int_least64_t = signed integer type;
    using int_leastN_t = see below; // optional, see below
    […]
    using uint64_t = unsigned integer type; // optional
    using uintN_t = see below; // optional, see below
    […]
    using uint_fast64_t = unsigned integer type;
    using uint_fastN_t = see below; // optional, see below
    […]
    using uint_least64_t = unsigned integer type;
    using uint_leastN_t = see below; // optional, see below
    
    using uintmax_t = unsigned integer type;
    using uintptr_t = unsigned integer type; // optional
    
    #define INT_N_MIN  see below;
    #define INT_N_MAX  see below;
    #define UINT_N_MAX  see below;
    
    #define INT_FASTN_MIN  see below;
    #define INT_FASTN_MAX  see below;
    #define UINT_FASTN_MAX  see below;
    
    #define INT_LEASTN_MIN  see below;
    #define INT_LEASTN_MAX  see below;
    #define UINT_LEASTN_MAX  see below;
    
    #define INTMAX_MIN  see below;
    #define INTMAX_MAX  see below;
    #define UINTMAX_MAX  see below;
    
    #define INTPTR_MIN  see below;
    #define INTPTR_MAX  see below;
    #define UINTPTR_MAX  see below;
    
    #define PTRDIFF_MIN  see below;
    #define PTRDIFF_MAX  see below;
    #define SIZE_MAX  see below;
    
    #define SIGATOMIC_MIN  see below;
    #define SIGATOMIC_MAX  see below;
    
    #define WCHAR_MIN  see below;
    #define WCHAR_MAX  see below;
    
    #define WINT_MIN  see below;
    #define WINT_MAX  see below;
    
    #define INTN_C(value)  see below;
    #define UINTN_C(value)  see below;
    #define INTMAX_C(value)  see below;
    #define UINTMAX_C(value)  see below;
    

    -1- The header also defines numerous macros of the form:

    INT_[FAST LEAST]{8 16 32 64}_MIN
    [U]INT_[FAST LEAST]{8 16 32 64}_MAX
    INT{MAX PTR}_MIN
    [U]INT{MAX PTR}_MAX
    {PTRDIFF SIG_ATOMIC WCHAR WINT}{_MAX _MIN}
    SIZE_MAX
    

    plus function macros of the form:

    [U]INT{8 16 32 64 MAX}_C
    

    -2- The header defines all types and macros the same as the C standard library header <stdint.h>. See also: ISO C 7.20

    -?- In particular, all types that use the placeholder N are optional when N is not 8, 16, 32 or 64. The exact-width types intN_t and uintN_t for N = 8, 16, 32, 64 are also optional; however, if an implementation provides integer types with the corresponding width, no padding bits, and (for the signed types) that have a two's complement representation, it defines the corresponding typedef names. Only those macros are defined that correspond to typedef names that the implementation actually provides. [Note: The macros INTN_C and UINTN_C correspond to the typedef names int_leastN_t and uint_leastN_t, respectively. — end note]

  2. Change 29.12.2 [cinttypes.syn] as indicated:

    #define PRIdNN see below
    #define PRIiNN see below
    #define PRIoNN see below
    #define PRIuNN see below
    #define PRIxNN see below
    #define PRIXNN see below
    #define SCNdNN see below
    #define SCNiNN see below
    #define SCNoNN see below
    #define SCNuNN see below
    #define SCNxNN see below
    #define PRIdLEASTNN see below
    #define PRIiLEASTNN see below
    #define PRIoLEASTNN see below
    #define PRIuLEASTNN see below
    #define PRIxLEASTNN see below
    #define PRIXLEASTNN see below
    #define SCNdLEASTNN see below
    #define SCNiLEASTNN see below
    #define SCNoLEASTNN see below
    #define SCNuLEASTNN see below
    #define SCNxLEASTNN see below
    #define PRIdFASTNN see below
    #define PRIiFASTNN see below
    #define PRIoFASTNN see below
    #define PRIuFASTNN see below
    #define PRIxFASTNN see below
    #define PRIXFASTNN see below
    #define SCNdFASTNN see below
    #define SCNiFASTNN see below
    #define SCNoFASTNN see below
    #define SCNuFASTNN see below
    #define SCNxFASTNN see below
    […]
    

    -1- The contents and meaning of the header <cinttypes> […]

    -?- In particular, macros that use the placeholder N are defined if and only if the implementation actually provides the corresponding typedef name in 17.4.1 [cstdint.syn], and moreover, the fscanf macros are provided unless the implementation does not have a suitable fscanf length modifier for the type.

[2018-04-03; Geoffrey Romer suggests improved wording]

Previous resolution [SUPERSEDED]:

This wording is relative to N4727.

  1. Change 17.4.1 [cstdint.syn], header <cstdint> synopsis, as indicated:

    […]
    using int64_t = signed integer type; // optional
    using intN_t = see below; // optional, see below
    […]
    using int_fast64_t = signed integer type;
    using int_fastN_t = see below; // optional, see below
    […]
    using int_least64_t = signed integer type;
    using int_leastN_t = see below; // optional, see below
    […]
    using uint64_t = unsigned integer type; // optional
    using uintN_t = see below; // optional, see below
    […]
    using uint_fast64_t = unsigned integer type;
    using uint_fastN_t = see below; // optional, see below
    […]
    using uint_least64_t = unsigned integer type;
    using uint_leastN_t = see below; // optional, see below
    
    using uintmax_t = unsigned integer type;
    using uintptr_t = unsigned integer type; // optional
    
    #define INT_N_MIN  see below;
    #define INT_N_MAX  see below;
    #define UINT_N_MAX  see below;
    
    #define INT_FASTN_MIN  see below;
    #define INT_FASTN_MAX  see below;
    #define UINT_FASTN_MAX  see below;
    
    #define INT_LEASTN_MIN  see below;
    #define INT_LEASTN_MAX  see below;
    #define UINT_LEASTN_MAX  see below;
    
    #define INTMAX_MIN  see below;
    #define INTMAX_MAX  see below;
    #define UINTMAX_MAX  see below;
    
    #define INTPTR_MIN  see below;
    #define INTPTR_MAX  see below;
    #define UINTPTR_MAX  see below;
    
    #define PTRDIFF_MIN  see below;
    #define PTRDIFF_MAX  see below;
    #define SIZE_MAX  see below;
    
    #define SIGATOMIC_MIN  see below;
    #define SIGATOMIC_MAX  see below;
    
    #define WCHAR_MIN  see below;
    #define WCHAR_MAX  see below;
    
    #define WINT_MIN  see below;
    #define WINT_MAX  see below;
    
    #define INTN_C(value)  see below;
    #define UINTN_C(value)  see below;
    #define INTMAX_C(value)  see below;
    #define UINTMAX_C(value)  see below;
    

    -1- The header also defines numerous macros of the form:

    INT_[FAST LEAST]{8 16 32 64}_MIN
    [U]INT_[FAST LEAST]{8 16 32 64}_MAX
    INT{MAX PTR}_MIN
    [U]INT{MAX PTR}_MAX
    {PTRDIFF SIG_ATOMIC WCHAR WINT}{_MAX _MIN}
    SIZE_MAX
    

    plus function macros of the form:

    [U]INT{8 16 32 64 MAX}_C
    

    -2- The header defines all types and macros the same as the C standard library header <stdint.h>. See also: ISO C 7.20

    -?- In particular, all types that use the placeholder N are optional when N is not 8, 16, 32 or 64. The exact-width types intN_t and uintN_t for N = 8, 16, 32, 64 are also optional; however, if an implementation provides integer types with the corresponding width, no padding bits, and (for the signed types) that have a two's complement representation, it defines the corresponding typedef names. Only those macros are defined that correspond to typedef names that the implementation actually provides. [Note: The macros INTN_C and UINTN_C correspond to the typedef names int_leastN_t and uint_leastN_t, respectively. — end note]

  2. Change 29.12.2 [cinttypes.syn] as indicated:

    #define PRIdNN see below
    #define PRIiNN see below
    #define PRIoNN see below
    #define PRIuNN see below
    #define PRIxNN see below
    #define PRIXNN see below
    #define SCNdNN see below
    #define SCNiNN see below
    #define SCNoNN see below
    #define SCNuNN see below
    #define SCNxNN see below
    #define PRIdLEASTNN see below
    #define PRIiLEASTNN see below
    #define PRIoLEASTNN see below
    #define PRIuLEASTNN see below
    #define PRIxLEASTNN see below
    #define PRIXLEASTNN see below
    #define SCNdLEASTNN see below
    #define SCNiLEASTNN see below
    #define SCNoLEASTNN see below
    #define SCNuLEASTNN see below
    #define SCNxLEASTNN see below
    #define PRIdFASTNN see below
    #define PRIiFASTNN see below
    #define PRIoFASTNN see below
    #define PRIuFASTNN see below
    #define PRIxFASTNN see below
    #define PRIXFASTNN see below
    #define SCNdFASTNN see below
    #define SCNiFASTNN see below
    #define SCNoFASTNN see below
    #define SCNuFASTNN see below
    #define SCNxFASTNN see below
    […]
    

    -1- The contents and meaning of the header <cinttypes> […]

    -?- PRI macros that use the placeholder N are defined if and only if the implementation actually provides the corresponding typedef name in 17.4.1 [cstdint.syn]. SCN macros that use the placeholder N are defined if and only if the implementation actually provides the corresponding typedef name and the implementation has a suitable fscanf length modifier for the type.

[2019-03-11; Reflector review and improved wording]

Wording simplifications due to new general two's complement requirements of integer types; removal of wording redundancies and applying some typo fixes in macro names.

[2019-03-16; Daniel comments and updates wording]

Hubert Tong pointed out that we do not have a statement about [U]INTPTR_{MIN|MAX} being optional. Interestingly, the C11 Standard does not say directly that the [U]INTPTR_{MIN|MAX} macros are optional, but this follows indirectly from the fact that intptr_t and uintptr_t are indeed optional. The updated wording therefore realizes Hubert's suggestion.

In addition, the reference document has been rebased to N4810, because that draft version contains an editorial change, which renames the term "range exponent" of integer types to "width", which is the vocabulary used below and also matches C's use.

Finally, Hubert Tong suggested the following rewording replacements of

If and only if the implementation defines such a typedef name, it also defines the corresponding macros.

to:

Each of the macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef name.

and of

PRI macros that use the placeholder N are defined if and only if the implementation actually defines the corresponding typedef name in 17.4.1 [cstdint.syn]. SCN macros that use the placeholder N are defined if and only if the implementation actually defines the corresponding typedef name and the implementation has a suitable fscanf length modifier for the type.

to:

Each of the macros listed in this subclause is defined if and only if the implementation actually defines the corresponding typedef name in 17.4.1 [cstdint.syn].

Those changes have been applied as well.

[2019-03-26; Reflector discussion and minor wording update]

Geoffrey pointed out that the revised wording has the effect that it requires an implementation to define SCN macros for all mentioned typedefs, but the C11 standard says "the corresponding fscanf macros shall be defined unless the implementation does not have a suitable fscanf length modifier for the type.". An additional wording update repairs this problem below.

Proposed resolution:

This wording is relative to N4810.

  1. Change 17.4.1 [cstdint.syn], header <cstdint> synopsis, as indicated:

    […]
    using int64_t = signed integer type; // optional
    using intN_t = see below; // optional, see below
    […]
    using int_fast64_t = signed integer type;
    using int_fastN_t = see below; // optional, see below
    […]
    using int_least64_t = signed integer type;
    using int_leastN_t = see below; // optional, see below
    […]
    using uint64_t = unsigned integer type; // optional
    using uintN_t = see below; // optional, see below
    […]
    using uint_fast64_t = unsigned integer type;
    using uint_fastN_t = see below; // optional, see below
    […]
    using uint_least64_t = unsigned integer type;
    using uint_leastN_t = see below; // optional, see below
    
    using uintmax_t = unsigned integer type;
    using uintptr_t = unsigned integer type; // optional
    
    #define INTN_MIN  see below
    #define INTN_MAX  see below
    #define UINTN_MAX  see below
    
    #define INT_FASTN_MIN  see below
    #define INT_FASTN_MAX  see below
    #define UINT_FASTN_MAX  see below
    
    #define INT_LEASTN_MIN  see below
    #define INT_LEASTN_MAX  see below
    #define UINT_LEASTN_MAX  see below
    
    #define INTMAX_MIN  see below
    #define INTMAX_MAX  see below
    #define UINTMAX_MAX  see below
    
    #define INTPTR_MIN  optional, see below
    #define INTPTR_MAX  optional, see below
    #define UINTPTR_MAX  optional, see below
    
    #define PTRDIFF_MIN  see below
    #define PTRDIFF_MAX  see below
    #define SIZE_MAX  see below
    
    #define SIG_ATOMIC_MIN  see below
    #define SIG_ATOMIC_MAX  see below
    
    #define WCHAR_MIN  see below
    #define WCHAR_MAX  see below
    
    #define WINT_MIN  see below
    #define WINT_MAX  see below
    
    #define INTN_C(value)  see below
    #define UINTN_C(value)  see below
    #define INTMAX_C(value)  see below
    #define UINTMAX_C(value)  see below
    

    -1- The header also defines numerous macros of the form:

    INT_[FAST LEAST]{8 16 32 64}_MIN
    [U]INT_[FAST LEAST]{8 16 32 64}_MAX
    INT{MAX PTR}_MIN
    [U]INT{MAX PTR}_MAX
    {PTRDIFF SIG_ATOMIC WCHAR WINT}{_MAX _MIN}
    SIZE_MAX
    

    plus function macros of the form:

    [U]INT{8 16 32 64 MAX}_C
    

    -2- The header defines all types and macros the same as the C standard library header <stdint.h>. See also: ISO C 7.20

    -?- All types that use the placeholder N are optional when N is not 8, 16, 32 or 64. The exact-width types intN_t and uintN_t for N = 8, 16, 32, 64 are also optional; however, if an implementation defines integer types with the corresponding width and no padding bits, it defines the corresponding typedef names. Each of the macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef name. [Note: The macros INTN_C and UINTN_C correspond to the typedef names int_leastN_t and uint_leastN_t, respectively. — end note]

  2. Change 29.12.2 [cinttypes.syn] as indicated:

    #define PRIdNN see below
    #define PRIiNN see below
    #define PRIoNN see below
    #define PRIuNN see below
    #define PRIxNN see below
    #define PRIXNN see below
    #define SCNdNN see below
    #define SCNiNN see below
    #define SCNoNN see below
    #define SCNuNN see below
    #define SCNxNN see below
    #define PRIdLEASTNN see below
    #define PRIiLEASTNN see below
    #define PRIoLEASTNN see below
    #define PRIuLEASTNN see below
    #define PRIxLEASTNN see below
    #define PRIXLEASTNN see below
    #define SCNdLEASTNN see below
    #define SCNiLEASTNN see below
    #define SCNoLEASTNN see below
    #define SCNuLEASTNN see below
    #define SCNxLEASTNN see below
    #define PRIdFASTNN see below
    #define PRIiFASTNN see below
    #define PRIoFASTNN see below
    #define PRIuFASTNN see below
    #define PRIxFASTNN see below
    #define PRIXFASTNN see below
    #define SCNdFASTNN see below
    #define SCNiFASTNN see below
    #define SCNoFASTNN see below
    #define SCNuFASTNN see below
    #define SCNxFASTNN see below
    […]
    

    -1- The contents and meaning of the header <cinttypes> […]

    -?- Each of the PRI macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef name in 17.4.1 [cstdint.syn]. Each of the SCN macros listed in this subclause is defined if and only if the implementation defines the corresponding typedef name in 17.4.1 [cstdint.syn] and has a suitable fscanf length modifier for the type.