Issue 1113: Questions about character constants

Authors: Jay Ghiron
Date: 2026-09-25
Submitted against: C23
Status: Open

Question 1

This includes interpreting character constants, which can involve converting escape sequences into execution character set members. Whether the numeric value for these character constants matches the value obtained when an identical character constant occurs in an expression (other than within a #if or #elif directive) is implementation-defined. Whether a single-character character constant may have a negative value is implementation-defined.

(C23 6.10.2 "Conditional inclusion" paragraph 13.)

Does this apply to UTF-8 character constants, UTF-16 character constants, and UTF-32 character constants? For example:

#if u'0'!=48
#error
#endif

Can this condition be true and cause an error? Note that C++ removed all wording which allowed character constants in conditional expression inclusion preprocessing directives to be different (see also C++ P2316).

Question 2

If __STDC_MB_MIGHT_NEQ_WC__ is not defined and the implementation uses a different encoding in conditional expression inclusion preprocessing directives for integer character constants and wchar_t character constants, must the implementation give equivalent values in conditional expression inclusion preprocessing directives for integer character constants and wchar_t character constants which both contain one character which is the same and is in the basic character set? For example:

#ifndef __STDC_MB_MIGHT_NEQ_WC__
#if'x'!=L'x'
#error
#endif
#endif

Can these conditions be true and cause an error?

Question 3

If __STDC_MB_MIGHT_NEQ_WC__ is defined, can the implementation give wchar_t character constants which contain one character in the basic character set a negative value if they occur outside of conditional expression inclusion preprocessing directives? For example:

static_assert(L'x'>0);

Can this condition be false and cause an error? Note that C++ requires such wchar_t character constants to have nonnegative values.

Question 4

If __STDC_MB_MIGHT_NEQ_WC__ is defined, do the requirements on decimal digits 0 through 9 being contiguous still apply to wchar_t character constants which contain one character that is a decimal digit if they occur outside of conditional expression inclusion preprocessing directives? For example:

static_assert(L'1'-L'0'==1);

Can this condition be false and cause an error? The same question would apply in C2Y to the hexadecimal digits a through f, and separately the hexadecimal digits A through F.

Question 5

If the implementation uses a different encoding in conditional expression inclusion preprocessing directives for character constants, do the same requirements on contiguous ranges of characters (such as decimal digits 0 through 9) also apply to character constants within conditional expression inclusion preprocessing directives? This applies to UTF-8 character constants, UTF-16 character constants, and UTF-32 character constants if question one is resolved as allowing different encodings for those character constants when inside of conditional expression inclusion preprocessing directives. If question four is resolved as not requiring contiguous ranges with wchar_t character constants outside of conditional expression inclusion preprocessing directives when __STDC_MB_MIGHT_NEQ_WC__ is defined, then this question would not apply to wchar_t character constants. For example:

#if'1'-'0'!=1
#error
#endif

Can this condition be true and cause an error?

Question 6

Can a character in the basic character set have a value in char that is not representable in int? This can only occur with CHAR_MAX>INT_MAX because of the requirements on char. If so, what would be the value of an integer character constant that contains such a character? Note that a negative value might make using it with one of the <ctype.h> functions undefined. Additionally, if '0'==INT_MAX is true then the decimal digits being contiguous would lose meaning since '0'+1=='1' would be undefined.

Question 7

Character constants, when evaluated in #if expressions, may be interpreted in the source character set, the execution character set, or some other implementation-defined character set. This latitude reflects the diversity of existing practice, especially in cross-compilers.

(Section 6.6 "Constant expressions" paragraph 3 C99 Rationale.)

The intent is to allow the source character set to be used for integer character constants and wchar_t character constants (other character constants did not exist in C99), but the source basic character set is smaller than the execution basic character set. Was it intended that '\a', '\b', '\n', '\r', and the equivalent wchar_t character constants must be valid despite the source basic character set not including them?

Question 8

If __STDC_MB_MIGHT_NEQ_WC__ is defined, is the encoding of the execution basic character set in wchar_t not locale-specific? That is, is L'x' valid for all locales?