我正在阅读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;
}
现在,我使用__
在stackoverflow上读取代码。 Windows中没有sys / syscall.h所以我们必须使用
#if __linux
#include <sys/syscall.h>
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
使用__
的确切位置以及b / w __
&amp;的区别是什么? _
。
在这里输入代码
答案 0 :(得分:17)
以下是the C standard所说的内容(第7.1.3节):
(该部分继续列出某些标准标题保留的特定标识符和标识符集。)
这意味着,例如,实现(编译器或标准头)可以使用名称__FOO
来它喜欢的任何内容。如果在自己的代码中定义该标识符,则程序的行为是未定义的。如果你“幸运”,你将使用一个不会定义它的实现,你的程序将按预期工作。
这意味着你不应该在你自己的代码中定义任何这样的标识符(除非你自己的代码是C实现的一部分 - 如果你不得不问,它不是)。无论如何都不需要定义这样的标识符;几乎没有任何未预留的标识符。
你可以使用_foo
之类的标识符,只要它在本地定义(不在文件范围内) - 但我个人觉得更容易避免使用前导下划线。
顺便提一下,_sqrt
的例子并不一定说明这一点。实现可以在_sqrt
中定义名称<math.h>
(因为那里定义的任何内容都在文件范围内),但是没有特别的理由期望它会这样做。编译程序时,我收到警告:
c.c:7:1: warning: implicit declaration of function ‘_sqrt’ [-Wimplicit-function-declaration]
因为我的系统上的<math.h>
没有定义该标识符,并且链接时发生致命错误:
/tmp/cc1ixRmL.o: In function `main':
c.c:(.text+0x1a): undefined reference to `_sqrt'
因为库中没有这样的符号。
答案 1 :(得分:5)
这是一个命名惯例,这意味着违反此规则不会立即直接导致破坏您的程序,但实际上真的真的真的非常[+无限次]一个跟随对话的好主意。
公约的实质是保留:
_
开头为语言实体命名,其中包括标准库__
开头命名在大多数情况下,它也是一个非常特定于平台的主题,许多供应商都尊重这一惯例,但他们也有自己的命名惯例和指南。
找到更多信息答案 2 :(得分:0)
<强> TL;博士你倒退了。在没有引导下划线的情况下命名您自己的东西,除非您正在为其他人编写库。标准库和编译器使用该技术来表示某些名称是内部的,而不是直接使用。
在C
中,没有名称空间。换句话说,文件中包含的所有名称都可能相互冲突。如果foo.h
和bar.h
都定义x
,那么当它们都被包含时会发生错误。
现在,x
是一个很常见的名字。几乎可以保证碰撞,foo.h
和bar.h
的作者必须意识到这一点。因此,为了避免将来使用其代码的程序员出现问题,他们将名称更改为_x
。
确实会出现常见名称。在诉诸强调之前,请尝试:
将私有与.c
和.h
个文件中的公共变量分开。大多数冲突名称都是私有的,不属于标题。
使用模块名称添加代码:foo_x
和bar_x
不会发生冲突。