c - 在 C 程序中使用 _ 和 __

标签 c

<分区>

我正在阅读 K&R 书。我阅读:

...name intended for use only by functions of the standard library begin with _ so they are less likely to collide with the names in the user program...

这到底是什么意思,请解释真正简单实用的方法。

我的理解是:

如果我想使用 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 上阅读了一段代码。 sys/syscall.h 在 Windows 中不存在,所以我们必须使用

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

__ 到底用在什么地方,___ 有什么区别。

最佳答案

这是the C standard说(第 7.1.3 节):

  • 所有以下划线和大写字母或其他字母开头的标识符 下划线始终保留用于任何用途。
  • 以下划线开头的所有标识符始终保留用作标识符 在普通和标记 namespace 中具有文件范围。

(本节继续列出特定的标识符和某些标准 header 保留的标识符集。)

这意味着,例如,实现(编译器或标准头文件)可以使用名称 __FOO 任何它喜欢的东西。如果您在自己的代码中定义该标识符,则您的程序的行为是未定义的。如果你“幸运”的话,你将使用一个没有碰巧定义它的实现,你的程序将按预期工作。

这意味着您根本不应该在自己的代码中定义任何此类标识符(除非您自己的代码是 C 实现的一部分——如果您不得不问,它不是)。无论如何都不需要定义这样的标识符;几乎不缺少未保留的标识符。

您可以使用像 _foo 这样的标识符只要它是在本地定义的(而不是在文件范围内)——但我个人发现完全避免使用前导下划线要容易得多。

顺便说一句,你的例子_sqrt不一定能说明问题。实现可以定义名称 _sqrt<math.h> (因为那里定义的任何东西都在文件范围内),但没有特别的理由期望它会这样做。当我编译你的程序时,我收到警告:

c.c:7:1: warning: implicit declaration of function ‘_sqrt’ [-Wimplicit-function-declaration]

因为<math.h>在我的系统上没有定义那个标识符,以及一个链接时 fatal error :

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

因为库中没有这样的符号。

关于c - 在 C 程序中使用 _ 和 __,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25090635/

相关文章:

python - 如何在 C 中创建具有不同列的二维数组?

c - strncpy 产生奇怪的输出

c - no-gui-app 的应用程序图标在 Dock 中弹跳了几分钟

c - 'vaGetDisplay' 和 `vaGetDisplayDRM' 的错误

c++ - 如何链接 C++ 以使用静态 C 库中定义的变量(找不到符号错误)

比较 C 中的 2 个字符串数组

c - 编译调用它们的内核驱动程序时,导出的 kvm 内核函数会收到未定义的警告

c - 未初始化的堆分配误解(代码有效——需要更正以消除 Valgrind 错误)

c++ - 转义 printf() 中的所有特殊字符

c - 估计 C 中条件运算符的数量