编写不可移植的 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
or前缀,但不能使用前缀...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 系统(示例)。这需要大量的移植工作,除非您知道要在 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 兼容性。