在查看CPython源代码时,我发现了一个名为listobject.c.h的文件.我不确定这个文件扩展名".c.h"是什么.该文件混合了函数原型和函数定义.有没有理由将.c添加到扩展名中,而不是只将其设置为.h文件?

我在谷歌上找不到任何关于这个文件扩展名的信息,因为他们删除了搜索查询中的特殊字符,所以我得到了关于.ch文件的信息.

推荐答案

它没有普遍适用的含义,但通常,它被用来暗示它是一个实现文件,由于构建系统的需要,它在另一个文件中是#include-ed的.

普通的头文件提供原型和声明,通常只提供声明为inlinestatic的内容的实现(甚至static也不受欢迎,除非使用链接时优化来消除其已编译版本的重复数据).提供其他类型的实现可能会在多个编译的目标文件中重复定义相同的可见实体,从而导致在链接时出现重复的问题.由于本例中的.c.h文件打算在exactly个一个文件中#include化(例如,longobject.c.h只打算包括在父目录的longobject.c中),因此#include化它没有问题,因为它不会创建重复的定义.

CPython专门使用它们的原因是the Argument Clinic.这是一个工具,可以让他们为内置生成优化的参数解析代码,而不必执行以下任一操作:

  1. 在逐个函数的基础上手动编写最佳解析代码,或者
  2. 依赖通用的、类似于printf的解析API,这些API很方便,但效率较低

作为一个额外的好处,当他们改进他们的解析框架和选项时(例如,当他们添加向量调用作为实现方法/函数的选项时),Argument Clinic可以在一个地方更新,并且好处立即在整个代码库中累积.

因为Argument Clinic在每次运行时都会从头开始重新生成文件,所以它们不能轻松地整合到手写的"真正的工作"实现函数中,而不会造成大量的代码混乱,并给提交补丁的人带来问题,因此他们将生成的代码分解到.c.h个文件中,以避免类似的冲突.

C++相关问答推荐

带双指针的2D数组

为什么PLT表中没有push指令?

是否有任何情况(特定类型/值),类型双关在所有符合标准的C实现中产生相同的行为?

为什么复合文字(C99)的返回会生成更多的汇编代码?

不会停在空格或换行符上的错误

我可以在C中声明不同长度数组的数组而不带变量名吗?

在C23中使用_GENERIC实现带有右值的IS_POINTER(P)?

如何在c++中包装返回空*的函数

如何将常量char*复制到char数组

致命:ThreadSaniizer:在Linux内核6.6+上运行时意外的内存映射

VS代码';S C/C++扩展称C23真关键字和假关键字未定义

加密解密工作正常,但返回错误0x80090005

如何在STM8项目中导入STM8S/A标准外设库(ST VisualDeveloper)?

在libwget中启用Cookie会导致分段故障

如何将大写/小写土耳其字母相互转换?

为什么我的半数组测试和奇数组测试不起作用?(我使用Assert进行调试)

即使我在C++中空闲,也肯定会丢失内存

在哪里可以找到叮当返回码的含义?

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

是什么阻止编译器优化手写的 memcmp()?