Path: csiph.com!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: u8"" c11 c23 Date: Mon, 20 Oct 2025 15:19:11 -0700 Organization: None to speak of Lines: 77 Message-ID: <875xc9p674.fsf@example.invalid> References: <10d5vck$3kufd$1@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Mon, 20 Oct 2025 22:19:16 +0000 (UTC) Injection-Info: dont-email.me; posting-host="7bc902c76e318c3a49b06a072798f8da"; logging-data="3713789"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/oHics7/5YcqiOArbbHHNM" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:RKFQL2NY96yTNvpf523VqlezSOk= sha1:567490bkvz5K9s927LtUKpKeZs0= Xref: csiph.com comp.lang.c:394603 Thiago Adams writes: > speaking on signed x unsigned, > > u8"a" in C11 had the type char [N]. Normally char is signed I would have said "commonly" rather than "normally". Not an important point. > in C23 it is unsigned char8_t [N]. > > when converting code from c11 to c23 we have a error here > const char* s = u8"" > > > I generally "cast char* " to "unsigned char*" when handling something > with utf8. I am not u8"" , I use just " " with utf8 encoded source > code and I just assume const char* is utf8. That raises another issue. The header was introduced in C99. In C99, C11, and C17, that header defines char16_t and char32_t. C23 introduces char8_t. There doesn't seem to be any way, other than checking the value of __STDC_VERSION__ to determine whether char8_t is defined or not. There are not *_MIN or *_MAX macros for these types, either in or in . A test program I just wrote would have been a little simpler if I could have used `#ifdef CHAR8_MAX`. Here's the test program : #include #include #define TYPEOF(x) \ (_Generic(x, \ char: "char", \ signed char: "signed char", \ unsigned char: "unsigned char", \ short: "short", \ unsigned short: "unsigned short", \ int: "int", \ unsigned int: "unsigned int", \ long: "long", \ unsigned long: "unsigned long", \ long long: "long long", \ unsigned long long: "unsigned long long")) int main(void) { printf("__STDC_VERSION__ = %ldL\n", __STDC_VERSION__); printf("u8\"a\"[0] is of type %s\n", TYPEOF(u8"a"[0])); #if __STDC_VERSION__ >= 202311L printf("char8_t is %s\n", TYPEOF((char8_t)0)); #endif printf("char16_t is %s\n", TYPEOF((char16_t)0)); printf("char32_t is %s\n", TYPEOF((char32_t)0)); } Its output with `gcc -std=c17` : __STDC_VERSION__ = 201710L u8"a"[0] is of type char char16_t is unsigned short char32_t is unsigned int Its output with `gcc -std=c23` : __STDC_VERSION__ = 202311L u8"a"[0] is of type unsigned char char8_t is unsigned char char16_t is unsigned short char32_t is unsigned int -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com void Void(void) { Void(); } /* The recursive call of the void */