当我今天阅读一些旧代码时,我注意到以下assert
行:
assert(('0' <= hexChar && hexChar <= '9')
|| ('A' <= hexChar && hexChar <= 'F')
|| ('a' <= hexChar && hexChar <= 'f'));
目的是断言hexChar
是十六进制数字([0-9A-Fa-f])。它通过依赖char
,'A'
,......,'B'
和'F'
,{{1} 'a'
个对象的类似ASCII的顺序来实现这一点。 },...,'b'
。
考虑到执行字符集是实现定义的,我开始想知道这是否总能达到我的意图。
第2.3节中的C ++标准,字符集,提及:
基本执行字符集和基本执行宽字符集应各自包含基本源字符集的所有成员,以及表示alert,backspace的控制字符和回车符,加上空字符(分别为 null宽字符),其表示具有全零位。对于每个基本执行字符集,成员的值应是非负的并且彼此不同。在源和执行基本字符集中,上述十进制数字列表中0之后的每个字符的值应比前一个值大1。 执行字符集和执行宽字符集分别是基本执行字符集和基本执行宽字符集的实现定义的超集。执行字符集的成员值和其他成员集是特定于语言环境的。
我将此解释为'f'
是可以的,因为('0' <= hexChar && hexChar <= '9')
,'0'
,...,'1'
是数字,每个数字的值都大于前一个。但是,其他基本源字符相对于彼此的顺序仍然是实现定义的。
这是正确的陈述吗?对C ++编译器一无所知(所以不知道实现细节),我是否需要重写'9'
如下所示?
assert
答案 0 :(得分:7)
第一行,与'0'
和'9'
的值进行比较,100%便携。 C语言保证所有实现都具有相同的行为。
第二行和第三行原则上是实现定义的,但从来没有,也永远不会是一个行为不同的实现。与C语言一起使用的唯一非ISO646兼容字符编码(以及C允许非ISO646兼容编码的唯一原因)是EBCDIC,它将字母'A'
放置到'F'
确切地说它们应该落在十六进制值的位置(通常字母在EBCDIC中是不连续的,但AF是一个连续的组)。
话虽如此,除非您需要支持传统大型机,否则尝试在C中“可移植”地处理基本字符编码没有任何价值。char
是8位,值0-127是ASCII,并且值128-255是区域设置或数据特定的多字节字符编码的一部分,我们有一天可以假设它始终是UTF-8。
答案 1 :(得分:5)
关于你的第一个问题:是的。
关于你的第二个问题:或许,但是你可能应该考虑使用C库isxdigit
函数或C ++语言环境变体。
答案 2 :(得分:3)
从技术上讲,C ++编译器使用其他字符编码是完全合法的。但是,实际情况是,您几乎肯定找不到这个代码不起作用的平台。由于新的主导字符编码是基于Unicode的,如UTF-16,并且Unicode共享ASCII集中所有字符的所有ASCII值,因此尤其如此。这是实现定义的唯一原因是,在编写标准的这一部分时仍然存在的非常非常旧的遗留平台 - 并且您必须在很大程度上重构代码以在任何非ASCII平台上运行。 / p>