使用前导下划线实际上会引起麻烦吗?

Does using leading underscores actually cause trouble?

本文关键字:麻烦 实际上 下划线      更新时间:2023-10-16

C/C++ 标准保留所有以下划线开头的标识符(如果不在全局命名空间中,则加上大写字母(或包含两个或多个相邻下划线的标识符。例:

int _myGlobal;
namespace _mine
{
    void Im__outta__control() {}
    int _LivingDangerously;
}

但是,如果我只是不在乎呢?如果我决定危险地生活并使用这些"保留"标识符怎么办?我到底会活得有多危险?

您是否真正见过由用户代码使用保留标识符而导致的编译器或链接器问题?

到目前为止,下面的答案相当于,"为什么要违反规则,因为这样做可能会造成麻烦?但是想象一下,你已经有一堆违反规则的代码。在什么时候,违反规则的麻烦成本会超过重构代码以遵守的成本?或者,如果程序员开发了一种需要野生下划线的个人编码风格(例如,可能来自另一种语言(会怎样?假设改变他们的编码风格对他们来说或多或少是痛苦的,那么什么会激励他们克服痛苦?

或者我可以反过来问同样的问题。C/C++ 库具体如何处理用户容易发生冲突的保留字?他们是否声明了可能造成名称冲突的全局变量?功能?类?当然,每个库都是不同的,但这种冲突通常如何表现?

教那些带着这类问题来找我的软件学生,我只能告诉他们,"这是违反规则的。这是一个迷信的、挥手的答案。此外,在二十年的C++编程中,我从未见过因违反保留字规则而导致的编译器或链接器错误。

一个好的怀疑论者,面对任何规则,都会问:"我为什么要关心?那么:我为什么要关心呢?

我现在

关心,因为我刚刚遇到了下划线,大而旧的代码库的失败,主要针对Windows并使用VS2005编译,但有些也交叉编译到Linux。 在分析较新的 gcc 更新时,我在 cygwin 下重建了一些,只是为了便于语法检查。 我从以下一行中得到了完全无法理解的错误(对我的小大脑(:

template< size_t _N = 0 > class CSomeForwardRef;

这产生了如下错误:

error: expected ‘>’ before numeric constant

谷歌在这个错误上出现了 https://svn.boost.org/trac/boost/ticket/2245 和 https://svn.boost.org/trac/boost/ticket/7203,这两者都暗示着一个流浪#define可能会妨碍。 果然,通过-E对预处理的源进行检查并通过包含路径进行搜索,发现了一些与位相关的.h(忘记哪个(定义了_N。 后来在同一次冒险中,我遇到了类似的_L问题。

编辑:不与位相关,但与字符相关:/usr/include/ctype.h - 以下是一些示例以及ctype.h如何使用它们:

#define _L      02
#define _N      04
.
.
.
#define isalpha(__c)    (__ctype_lookup(__c)&(_U|_L))
#define isupper(__c)    ((__ctype_lookup(__c)&(_U|_L))==_U)
#define islower(__c)    ((__ctype_lookup(__c)&(_U|_L))==_L)
#define isdigit(__c)    (__ctype_lookup(__c)&_N)
#define isxdigit(__c)   (__ctype_lookup(__c)&(_X|_N))

我将扫描源中所有带下划线的标识符,并通过重命名我们错误创建的所有标识符来清除......

乔恩

结果可能会根据您将使用的特定编译器而有所不同。关于"危险级别" - 每次你会遇到错误 - 你将不得不怀疑它是否源于你实现的逻辑或你没有使用标准的事实。

但这还不是全部...假设有人告诉你:"这是绝对安全的!因此,您可以毫无问题地做到这一点(仅假设..(当你遇到一个错误时,它会重新定义你的想法吗,或者你仍然会想知道是否有轻微的追逐他错了?:)

所以,你看,无论你得到哪个答案,它都不可能是一个好的答案。(这让我实际上喜欢你的问题(

我到底会有多危险?
危险到足以在下次编译器升级中破坏代码。

想想未来,您的代码可能无法移植,并且将来可能会中断,因为您的实现的未来增强版本可能与您使用的符号名称完全相同。

由于这个问题有一点:"它可能错了,但它能错到什么程度,什么时候错过">的味道,我认为墨菲定律相当恰当地回答了这一点:

"任何可能出错的事情都会出错(当你最不期望的时候("。 [#]

[#] ()是我的发明,不是墨菲的。

如果您尝试在实际存在冲突的地方构建代码,您将看到奇怪的构建错误,或者更糟糕的是,根本没有构建错误和不正确的运行时行为。

我见过有人使用保留标识符,当它导致新平台上的构建问题时,必须更改该标识符。

这不太可能,但没有理由这样做。