Authors: Jay Ghiron
Date: 2026-10-14
Submitted against: C23
Status: Open
Cross-references: 0265, 1113
For the following questions assume that the following macro is always defined:
#define IGNORE(...)
The same considerations apply to each element of the sequence in a string literal as if it were in an integer character constant (for a character or UTF-8 string literal) or a wide character constant (for a wide string literal), except that the single-quote
'is representable either by itself or by the escape sequence\', but the double-quote"shall be represented by the escape sequence\".
(C23 6.4.6 "String literals" paragraph 4.)
This appears to apply the constraints of octal escape sequences and hexadecimal escape sequences as specified earlier for character constants to string literals. Does this apply the constraints before string literal concatenation or after string literal concatenation? For example:
const typeof(u' ')a[]=u"""\400";
If CHAR_BIT is eight, it is unclear whether or not this declaration
has a constraint violation.
Do the constraints on octal escape sequences and hexadecimal escape sequences apply to preprocessing tokens which are never converted to tokens? For example:
IGNORE('\400')
IGNORE("\400")
#if 0
'\400'
"\400"
#endif
Must these invalid octal escape sequences be rejected if CHAR_BIT is
eight? If question one is resolved as applying the constraints after
string literal concatenation, then the answer for string literals is
obvious.
Do the constraints on universal character names apply to string literal preprocessing tokens and character constant preprocessing tokens which in either case are never converted to tokens? For example:
IGNORE('\uD800')
IGNORE("\uD800")
#if 0
'\uD800'
"\uD800"
#endif
GCC, Clang, MSVC, and EDG all accept this and the example in question two. Inside of skipped groups there is disagreement about whether the constraints apply to identifiers and preprocessing numbers: GCC and Clang reject, while MSVC and EDG accept.
For the purposes of this token conversion and evaluation, all signed integer types and all unsigned integer types act as if they have the same representation as, respectively, the types
intmax_tanduintmax_tdefined in the header<stdint.h>. This includes interpreting character constants, which can involve converting escape sequences into execution character set members.
(C23 6.10.2 "Conditional inclusion" paragraph 13.)
Does this mean that inside of conditional expression inclusion
preprocessing directives the constraints on character constants are
based on uintmax_t? For example:
#if'\400'
#endif
Is this valid when CHAR_BIT is eight? If the range of char is
interpreted as being affected because both signed char and unsigned char are affected, then it appears that this could also affect the
resulting value:
#if'\377'==-1
#error
#endif
Is this valid for any value of CHAR_MAX? GCC, Clang, MSVC, and EDG
all reject both of the previous examples in this question. It should
also be considered if character constants that contain a single
character or a single escape sequence which in either case is in the
basic character set (source or execution depending upon how issue
1113 is resolved) can have a value not normally possible:
#include<limits.h>
#if'a'>CHAR_MAX
#error
#endif
Can this be invalid? See also DR 265.