为啥在这个 C 代码中字母表被分成多个范围?

Posted

技术标签:

【中文标题】为啥在这个 C 代码中字母表被分成多个范围?【英文标题】:Why is the alphabet split into multiple ranges in this C code?为什么在这个 C 代码中字母表被分成多个范围? 【发布时间】:2015-07-15 00:13:34 【问题描述】:

在一个自定义库中我看到了一个实现:

inline int is_upper_alpha(char chValue)

    if (((chValue >= 'A') && (chValue <= 'I')) ||
        ((chValue >= 'J') && (chValue <= 'R')) ||
        ((chValue >= 'S') && (chValue <= 'Z')))
        return 1;
    return 0;

这是Easter egg 还是与标准 C/C++ 方法相比有什么优势?

inline int is_upper_alpha(char chValue)

    return ((chValue >= 'A') && (chValue <= 'Z'));

【问题讨论】:

请注意,在 EBCDIC 中,小写字母的字符范围在大写字母的字符范围之前,并且都在数字之前——这与 ASCII 中的顺序正好相反——基于编码(例如 8859-x 系列、Unicode、CP1252 或……)。 注意:如果'J' - 'I''S' - 'R' 都等于1,那么我希望一个合理的优化器会将前者变成后者。 【参考方案1】:

这段代码的作者大概不得不在某个时候支持EBCDIC,其中字母的数值是不连续的(IJRS 之间存在间隙,你可能已经猜到了)。

值得注意的是,C 和 C++ 标准仅保证字符 09 正是出于这个原因具有连续的数值,因此这两种方法都不是严格符合标准的。

【讨论】:

真正的WTF是为什么原作者没有发表评论:// In the EBCDIC coding, the alphabet has gaps between these values. See URL: xxxx for details。那么你甚至不必问这个问题。您将在代码中找到答案。 @abelenky 如果代码最初是用于通常使用 ebcdic 的系统,那么它在当时可能看起来很明显并且不需要注释,不幸的是,在遗留代码中看起来很好的事情现在看起来很奇怪。 @abelenky:真正的 WTF是为什么原作者没有使用标准功能,即return ( isalpha( chValue ) &amp;&amp; isupper( chValue ) )... @Damon:这不是问题所在。即使在本机不使用该编码的系统上,您也可能必须处理“外来”编码。所以你将你的语言环境设置为给定的编码,然后你必须保持手指交叉,程序员实际上使用标准函数而不是像上面那样进行“智能”编码,认为他知道他的程序将遇到的每一种编码...... 如果从 1970 年代开始编写它以支持 EBCDIC,那么 isalpha 和 isupper 甚至是 ANSI 还是当时大多数编译器都支持?【参考方案2】:

看起来它试图同时覆盖 EBCDIC 和 ASCII。您的替代方法不适用于 EBCDIC(它有误报,但没有误报)

C 和 C++ 要求'0'-'9' 是连续的。

请注意,标准库调用确实知道它们是否在 ASCII、EBCDIC 或其他系统上运行,因此它们更便携,可能更高效。

【讨论】:

std::isupper实际上是查询当前安装的全局C语言环境。 是的,你是对的。该方法是为覆盖两种编码而编写的。感谢您的回答! @Lingxi:没错,但这并不意味着您可以将语言环境从 ASCII 切换到 EBCDIC。 'A' 必须保持 'A' 与区域设置无关。 ASCII 转 UTF-8,这是可能的。 @Lingxi:std::isupper查询当前安装的全局C语言环境,是的,但是解释字符文字的编译阶段没有。 @Lingxi - 请注意。在大多数情况下是否真的需要std::isupper 是值得怀疑的。它尊重用于用户输入的语言环境。但是在解析文件、与数据库交互时,您通常需要一些其他语言环境。此外,至少在 Linux 上,这些与语言环境相关的调用非常慢 - 例如,std::isalpha 在实际比较单个字符之前调用了两次 dynamic_cast 以“找到”正确的语言环境实现。

以上是关于为啥在这个 C 代码中字母表被分成多个范围?的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中定义字母的范围

为啥函数被描述为块范围

为啥这个javascript函数失去了闭包范围?

为啥共享指针在 main 末尾没有超出范围?

为啥在这种情况下无法访问全局范围? [复制]

spark分区