- 此问题在此处已有答案**:
What does double underscore ( __const) mean in C?(4个答案)
What is the reason for underscore in C variable name definition?(3个答案)
八年前就关门了。
我在读K & R的书。我读到:
...仅由标准库函数使用的名称以_
开头,因此它们不太可能与用户程序中的名称冲突...
这到底是什么意思请解释真正简单实用的方法。
我的理解是:
如果我想使用math.h中定义的sqrt,那么
#include <math.h>
#define sqrt(x) x*x*x
main()
{
int x=4;
_sqrt(x); // That is from the header file math.h
sqrt(x); // my own defined macro
/*or its the reverse way _sqrt for my own defined macro so it won't collide with original sqrt i.e. without _ for sqrt from math.h */
return 0;
}
现在,我读了一段使用__
的堆栈溢出代码。sys/syscall. h在Windows中不存在,因此我们必须使用
#if __linux
#include <sys/syscall.h>
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
__
的确切使用位置以及__
和_
之间的区别是什么。
3条答案
按热度按时间bpzcxfmw1#
the C standard的说明如下(第7.1.3节):
(The部分继续列出特定的标识符和由某些标准报头保留的标识符集合)。
这意味着,例如,实现(编译器或标准头文件)可以使用名称
__FOO
表示 * 任何它喜欢的 *。如果你在自己的代码中定义了这个标识符,你的程序的行为是未定义的。如果你“幸运”,你将使用一个碰巧没有定义它的实现,你的程序将按预期工作。这意味着您不应该在自己的代码中定义任何这样的标识符(除非您自己的代码是C实现的一部分--如果您不得不问,它不是)。几乎不缺少未保留的标识符。
您可以使用像
_foo
这样的标识符,只要它是在本地定义的(而不是在文件范围内)--但我个人发现,完全避免使用前导下划线要容易得多。顺便说一句,你的
_sqrt
例子并不一定说明这一点,一个实现 * 可能 * 在<math.h>
中定义名称_sqrt
(因为那里定义的任何东西都在文件作用域),但没有特别的理由期望它会这样做,当我编译你的程序时,我得到一个警告:因为我系统上的
<math.h>
* 没有 * 定义该标识符,以及链接时的致命错误:因为库中没有这样的符号。
fcipmucu2#
这是一个命名约定,这意味着违反这个规则不会立即直接导致程序崩溃,但遵循这个约定是一个非常非常非常非常非常非常[ +无限次]的好主意。
公约的实质是保留:
_
开头的语言实体命名,其中包括标准库__
开头的编译器内部命名大多数情况下,这也是一个特定于平台的主题,许多供应商都遵守这一约定,但他们也有自己的命名约定和准则。
您可以通过搜索c double underscore naming convention找到更多信息
py49o6xq3#
tl; dr你弄反了。给你自己的东西命名时不要用下划线,除非你是在为别人写库。标准库和编译器使用这种技术来表示某些名字是内部的,不能直接使用。
强调独特性
在
C
中,没有命名空间。换句话说,包含在文件中的所有名称都可能相互冲突。如果foo.h
和bar.h
都定义了x
,则当它们都包含在内时将发生错误。现在,
x
是一个非常常见的名称,几乎可以肯定会发生冲突,foo.h
和bar.h
的编写者必须意识到这一点,因此,为了避免将来使用他们代码的程序员出现问题,他们将名称改为_x
。替代品
常见名称确实存在。在使用下划线之前,请尝试:
1.在
.c
和.h
文件中分离私有变量和公共变量。大多数冲突名称是私有的,不属于头文件。1.在代码前面加上模块的名称:
foo_x
和bar_x
不会冲突。