在我编写的C语言库中,我发现大多数操作都过于冗长,因此我尝试使其简洁 - 通过使用宏和保留
_
标识符。
据我了解,以
_
开头的标识符是为 C 标准、实现和库保留的;但没有单独提及_
。我明智地猜测它可以被程序(即应用程序)使用。
这种做法并不新鲜,
$_
在 Perl 中经常使用,并且有很多习惯用法。在Python和一些shell/脚本语言中,_
也指最后一个表达式的值。
当然,我不会直接连接脚本语言。在 C 中使用词法本地
_
标识符时需要注意什么?以及其他一些系统编程语言(例如 Rust、C++)?由此会产生什么样的互操作性问题?
C标准在C17 7.1.3中具体说的是:
- 以下划线和大写字母或另一个下划线开头的所有标识符始终保留以供任何使用,但在词法上与关键字相同的标识符除外。
- 所有以下划线开头的标识符始终保留用作普通名称空间和标记名称空间中文件范围的标识符。
用简单的英语来说,这意味着:
__
或_A
(任何大写字母)开头的标识符是为编译器和编译器的标准库保留的(详细信息请参见:“保留供任何使用”是什么意思?)。因此,如果您使用此类标识符,您可能会与标准库发生命名冲突。_
开头的任何标识符都保留在您在函数外部声明任何内容时(包括声明函数时)使用。所以这意味着你不应该编写如下代码:
// BAD
int _;
void f (void)
{
// ...
}
或
// BAD
void _ (void);
否则您可能会遇到命名冲突。但是,您可以编写类似的代码
// OK
void f (void)
{
int _ = something;
}
或
// OK
#define x(_) _
int main() {
int _ = x(5);
printf("%d",_);
}
宏参数不是文件范围标识符,而是在 main() 内部扩展和解析。
话虽如此,出于任何目的命名变量
_
都是一个糟糕的主意。如果您发现某些代码过于冗长,那么您至少可以想出一个更具描述性的 3 个字母标识符吗? val
、cnt
、fun
、adr
、tmp
等我只见过标识符 _
在代码高尔夫、代码混淆或“冒充”无意义的外来 C 功能知识的情况下使用。因此,如果您真正考虑使用
_
,请知道您发现自己属于这些类别之一。这对于一个人的代码来说并不讨人喜欢——在下一次代码审查中被屠杀。