UINTN_C(value)This issue has been automatically converted from the original issue lists and some formatting may not have been preserved.
Authors: WG14, Rajan Bhakta
Date: 2014-03-05
Reference document: N1798
Submitted against: C11 / C17
Status: Closed
Converted from: n2396.htm
With reference to ISO/IEC WG14 N1569, subclause 7.20.4.1: The macro
UINTN_C(value) shall expand to an integer constant expression
corresponding to the type uint_leastN_t.
7.20.4 p1 imposes a stricter requirement on the form of the expansion; it must be an integer constant (for which paragraph 2 points to 6.4.4.1).
The type described in 7.20.4 p3 for the result of the expansion has an
interesting property; we observe this for uint_least16_t without reference to
the UINT16_C macro by using u'\0' in a context where it will be first
promoted as part of the usual arithmetic conversions:
#include <assert.h>
#if u'\0' - 1 < 0
// Types: #if (uint_least16_t) - (signed int) < (signed int)
// Due to 6.10.1 p4, near the reference to footnote 167,
// after applying the integer promotions as part of 6.3.1.8 p1
// to the operands of the subtraction, the expression becomes:
// Types: #if (unsigned int) - (signed int) < (signed int)
// Following 6.3.1.8 p1 through to the last point gives:
// Types: #if (unsigned int) - (unsigned int) < (signed int)
// Result: false
# error Expected large unsigned value.
#endif
int main(void) {
// Types: assert((uint_least16_t) - (signed int) < (signed int))
// Assuming that signed int can represent all values of uint_least16_t,
// after applying the integer promotions as part of 6.3.1.8 p1
// to the operands of the subtraction, the expression becomes:
// Types: assert((signed int) - (signed int) < (signed int))
// Result: true
assert(u'\0' - 1 < 0);
return 0;
}
The code presented should neither fail to compile nor abort when executed (for
example) on a system using two's complement and 8, 16 and 32 bits (respectively)
for char, short and int with no padding bits.
Consider the case for N = 8 or 16 on systems with INT_MAX as +2147483647,
UCHAR_MAX as 255 and USHRT_MAX as 65535: it is unclear how a macro can be
formed such that it expands to an integer constant that has the promoted signed
int type in phase 7 of translation and also the promoted unsigned int type in
phase 4 of translation without special (non-standard) support from the compiler.
Even if the requirement for an integer constant is relaxed to only require an
integer constant expression, the case for N = 8 on systems with INT_MAX as
+32767 and UCHAR_MAX as 255 remains a problem without the use of casts (since
uint_least16_t, for which we can form a literal, has different promotion
behaviour from uint_least8_t).
Implementations seen:
#define UINT8_C(c) c ## U#define UINT8_C(c) cDR 209 seemed to try to address the issue of needing special compiler support in order to define the macros for integer constants; however, the problem seems to remain.
UINT{8,16}_C macros from the standard.Comment from WG14 on 2015-10-29:
Apr 2014 meeting
Oct 2014 meeting
The committee believes that DR209 is still appropriate in that "compiler magic" must be used for the implementation of these macros. The committee does not consider this a defect.
As such, both proposed resolutions were found inappropriate.