当前位置: 首页 > 知识库问答 >
问题:

在 C 程序中使用 _ 和 __ [复制]

朱岳
2023-03-14

我在读 K

...仅供标准库函数使用的名称以 _ 开头,因此它们不太可能与用户程序中的名称发生冲突...

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

我的理解是:

如果我想使用在 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个答案

冯元魁
2023-03-14

tl;博士你把它倒过来了。命名你自己的东西而不带前导下划线,除非你正在为别人编写一个库。标准库和编译器使用该技术来指示某些名称是内部名称,而不是直接使用。

C 中,没有命名空间。换句话说,文件中包含的所有名称都可以相互冲突。如果 foo.hbar.h 都定义了 x,则当它们都包含在内时将发生错误。

现在,x是一个非常常见的名字。碰撞几乎是必然的,foo.h和bar.h的作者必须意识到这一点。因此,为了避免将来使用其代码的程序员出现问题,他们将名称更改为_x

确实会出现通用名称。在诉诸低估评分之前,请尝试:

>

  • .c.h 文件中分离私有变量和公共变量。大多数冲突名称都是私有的,不属于标头。

    在代码前面加上模块的名称:foo_xbar_x 不会冲突。

  • 卫英悟
    2023-03-14

    这是一个命名约定,这意味着违反此规则不会立即直接导致破坏您的程序,但是遵循约定是一个非常非常非常 - 非常

    公约的本质是保留:

    • _ 开头的语言实体命名,其中包括标准库
    • __ 开头的命名表示编译器内部

    大多数时候,这也是一个真正的平台特定主题,许多供应商尊重此约定,但他们也有自己的命名约定和准则。

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

    江智
    2023-03-14

    以下是 C 标准的内容(第 7.1.3 节):

    • 所有以下划线和大写字母或其他下划线开头的标识符始终保留供任何使用。
    • 所有以下划线开头的标识符始终保留为在普通命名空间和标记命名空间中具有文件范围的标识符。

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

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

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

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

    顺便说一下,你的_sqrt例子并不一定说明这一点。实现可以定义名称 _sqrt

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

    因为

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

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

     类似资料:
    • 问题内容: 在C ++程序中使用Redis数据库的最佳方法是什么? 问题答案: 使用C绑定库?似乎在任何地方都没有C ++包装器。

    • 问题内容: 因此,我正在使用C#开发一个应用程序以从Web读取一些信息,但这是一个Windows窗体应用程序。我得到一个JSON字符串,我需要从中获取一些信息。我知道有一个用于C#Web应用程序的库,但是如何在Windows窗体应用程序中使用呢? 问题答案: 那里有许多JSON库。您可以考虑以下三个建议: Json.NET ,一个相当流行的JSON(反序列化)库。 ****根据 ServiceSt

    • 我正在用c开发一个应用程序,我想使用solr来索引sqlite数据库,我在网上搜索了一下,发现我需要使用JNI:http://randr . svbtle . com/experiment-with-embedded-Solr-in-Java-and-c,但是我发现jar有很多问题(我使用了\solr-4.9.0\dist\solrj-lib和\solr-4.9.0\dist和\solr-4.9.

    • 实现 (Implementation) 现在,我们将看到该计划的实际执行情况 - #include <stdio.h> int main() { char s1[] = "TajMahal"; // String Given char s2[8]; // Variable to hold value int length = 0;

    • 我做了一个C应用程序,它假设使用Kerberos身份验证来访问HDFS。这个应用程序的webserver也是用C编写的。 我正在尝试使用Kerberos票证在此应用程序中进行透明身份验证。 我使用以下命令对未经授权的用户进行了服务器响应: HTTP/1.1 401未经授权 WWW-认证:协商 浏览器会对标题中的授权字段做出反应,如下所示: 授权:协商Yiecgygkwybbqucoid/jCCA/

    • 在WP8.1中创建了一个集线器应用程序,我有一个列表视图,当按下appbar按钮时,我需要修改选择模式。我无法访问后面的。cs代码中给listview的x:name。我已经在一个正常的页面上工作了,只是在集线器应用程序中不工作。 我无法访问C#中的x:name=“WeatherListView”来更改selectionmode 私有void WeatherRemoveAppBarButton_On

    • 我正在尝试在Docker容器中安装mongocxx驱动程序,第一步是使用package Manager安装mongo-c驱动程序。我精简的DockerFile: 完成此步骤后,我应该可以按照以下说明安装cxx驱动程序:https://mongodb.github.io/mongo-cxx-driver/mongocxx-v3/installation/ 有人有过在Docker实例中安装的经验吗?你

    • 我正在尝试使用Rest服务,该服务接收带有密钥的图像。我正在Visual Studio 2017中使用RestSharp v.106.10.1。我有下面的代码,执行时返回一条带有服务器响应的消息,表示包到达时没有映像。你能帮我弄清楚我做错了什么吗?。 这是我的密码 邮递员寄信的方式是这样的。头contentType:application/x-www-form-urlencoded,表单数据中的主