在C程序中使用_和__

12 c

我正在读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;
}
Run Code Online (Sandbox Code Playgroud)

现在,我使用了在stackoverflow上读取代码__.sys/syscall.h在Windows中不存在,所以我们必须使用

#if __linux 
#include <sys/syscall.h>
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
Run Code Online (Sandbox Code Playgroud)

确切__使用的地方和b/w __&的区别_.在此处输入代码

Kei*_*son 19

这是C标准所说的内容(第7.1.3节):

  • 所有以下划线开头的标识符以及大写字母或另一个下划线始终保留用于任何用途.
  • 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符.

(该部分继续列出特定标识符和某些标准标题保留的标识符集.)

这意味着,对于例如,执行(编译器或者一个标准的头),可以使用名称__FOO任何它喜欢.如果在自己的代码中定义该标识符,则程序的行为是未定义的.如果你"幸运",你将使用一个不会定义它的实现,你的程序将按预期工作.

这意味着你不应该在你自己的代码中定义任何这样的标识符(除非你自己的代码是C实现的一部分 - 如果你不得不问,它不是).无论如何都不需要定义这样的标识符; 几乎没有任何未预留的标识符.

您可以使用标识符_foo,只要它在本地定义(不在文件范围内) - 但我个人觉得更容易避免使用前导下划线.

顺便提一下,你的例子_sqrt并不一定说明这一点.一个实现可以定义名称_sqrt<math.h>(因为任何定义有在文件范围内),但没有特别的理由认为它会这么做.当我编译你的程序时,我收到一个警告:

c.c:7:1: warning: implicit declaration of function ‘_sqrt’ [-Wimplicit-function-declaration]
Run Code Online (Sandbox Code Playgroud)

因为<math.h>在我的系统上没有定义该标识符,以及链接时致命错误:

/tmp/cc1ixRmL.o: In function `main':
c.c:(.text+0x1a): undefined reference to `_sqrt'
Run Code Online (Sandbox Code Playgroud)

因为图书馆里没有这样的符号.

  • 是的,文件范围静态函数仍然是文件范围,因此以“_”开头的名称仍然保留在该上下文中。实际上,最简单的事情就是*永远不要*声明名称以“_”开头的东西(除非您正在编写实现的一部分)。不要使用名称“sqrt”,因为“&lt;math.h&gt;”可能将其定义为宏。更一般地说,我不会重复使用标准库定义的任何名称,只是为了避免混淆,即使它处于安全上下文中。(例如,不要将日志记录函数称为“log”,因为这是自然对数函数的名称。) (2认同)

use*_*710 5

这是一个命名惯例,这意味着违反这个规则不会立即直接导致破坏你的程序,但实际上真的真的非常真实[+无限次]一个跟随对话的好主意.

公约的实质是保留:

  • 命名从_语言实体开始,包括标准库
  • __编译器内部开始命名

它在大多数时候也是一个非常特定于平台的主题,许多供应商都尊重这个惯例,但他们也有自己的命名约定和指南.

您可以通过搜索c双下划线命名约定找到更多


归档时间:

查看次数:

34848 次

最近记录:

9 年,8 月 前