为什么在C11或C++11中即使有UTF-8字符串也没有UTF-8字符呢?我知道,一般来说,一个字符字面代表一个ASCII字符,它等同于一个单八位字节的UTF-8代码点,但C和C++都没有规定编码必须是ASCII。
基本上,如果我没看错标准,不能保证'0'将表示整数0x30,但u8"0"必须表示字符序列0x30 0x00。
编辑:
我知道并不是每个UTF-8代码点都适合一个字符。这样的字面量只适用于单八位字节的代码点(也就是ASCII),所以我猜将其称为"ASCII字符字面量“会更合适,所以问题仍然存在。我只是选择使用UTF-8来解决这个问题,因为有UTF-8字符串文字。我能想象的唯一一种保证ASCII值可移植的方法是为每个字符写一个常量,考虑到只有128个字符,这并不是那么糟糕,但仍然...
发布于 2012-06-08 04:07:52
编写不可移植的C代码是完全可以接受的,这也是这么做的众多理由之一。您可以随意假设您的系统使用ASCII或其超集,并警告您的用户,他们不应该尝试在EBCDIC系统上运行您的程序。
如果你觉得非常慷慨,你可以编码一张支票。已知gperf程序会生成包含此类检查的代码。
_Static_assert('0' == 48, "must be ASCII-compatible");或者,对于C11之前的编译器,
extern int must_be_ascii_compatible['0' == 48 ? 1 : -1];如果您使用的是C11,则可以对字符常量使用u或U前缀,但不能使用u8前缀...
/* This is useless, doesn't do what you want... */
_Static_assert(0, "this code is broken everywhere");
if (c == '々') ...
/* This works as long as wchar_t is UTF-16 or UTF-32 or UCS-2... */
/* Note: you shouldn't be using wchar_t, though... */
_Static_assert(__STDC_ISO_10646__, "wchar_t must be some form of Unicode");
if (c == L'々') ...
/* This works as long as char16_t is UTF-16 or UCS-2... */
_Static_assert(__STDC_UTF_16__, "char16_t must be UTF-16");
if (c == u'々') ...
/* This works as long as char32_t is UTF-32... */
_Static_assert(__STDC_UTF_32__, "char32_t must be UTF-32");
if (c == U'々') ...有一些项目是用非常可移植的C编写的,并且已经移植到了非ASCII码系统(example)。这需要大量的移植工作,除非您知道要在EBCDIC系统上运行代码,否则没有真正的理由去做这些工作。
标准上的:编写C标准的人必须与每一种可能的C实现抗争,包括一些非常奇怪的实现。有一些已知的系统,其中sizeof(char) == sizeof(long)、CHAR_BIT != 8、整数类型具有陷阱表示,sizeof(void *) != sizeof(int *)、sizeof(void *) != sizeof(void (*)())、va_list是堆分配的,等等。这是一场噩梦。
不要试图编写在你从未听说过的系统上运行的代码,也不要努力寻找C标准中的保证。
例如,就C标准而言,以下是malloc的有效实现
void *malloc(void) { return NULL; }请注意,虽然可以保证u8"..."常量为UTF-8,但u"..."和U"..."不能保证编码为每个字符16位和32位,并且必须由实现记录实际的编码。
摘要:在2012年可以安全地承担ASCII码兼容性。
发布于 2015-06-17 00:01:50
对于C++,Evolution Working Group issue 119: Adding u8 character literals已经解决了这个问题,他的动机部分说:
我们有五个编码前缀,用于字符串文字(none,L,u8,u,U),但只有四个用于字符文字--缺少的一个是u8。如果窄执行字符集不是ASCII码,那么u8字符文字将提供一种使用保证ASCII码编写字符文字的方法(单码单元u8编码恰好是ASCII码)。添加对这些文字的支持将添加一个有用的功能,并使语言稍微更一致。
EWG讨论了在Rapperswil中添加u8字符文字的想法,并接受了这一更改。本文提供了该扩展的措辞。
这是使用N4267: Adding u8 character literals的措辞合并到工作草案中的,我们可以在目前最新的标准草案N4527中找到措辞,并注意到2.14.3部分说它们仅限于适合单个UTF-8代码单元的代码点:
以u8开头的字符文字,例如u8'w',是字符类型的字符文字,称为
-8字符文字。UTF-8字符文字的值等于其ISO10646代码点值,前提是该代码点值可用单个UTF-8代码单元表示(即,如果它是US-ASCII字符)。包含多个c字符的UTF-8字符文本的格式不正确。
发布于 2012-06-08 03:33:01
如果您不相信您的编译器会将'0'视为ASCII字符0x30,那么您可以改用static_cast<char>(0x30)。
https://stackoverflow.com/questions/10938306
复制相似问题