【问题标题】:Why don't Standard C Libraries need to be divided into a header and implementation file?为什么标准 C 库不需要分为头文件和实现文件?
【发布时间】:2018-07-10 01:57:00
【问题描述】:

当在 C++ 中创建一个类,或者在 C 中使用 structs 创建一个 等价物 时,最好将它分成两个文件:一个头文件(用于声明)和一个实现文件(用于实际定义方法等)。

这样做是因为如果方法定义存在于多个文件中,它们可能会发生冲突(并且包含保护不能阻止这种情况,因为宏只存在于定义它们的文件中,并被复制到包含它们的文件中; 包含守卫防止在同一个文件中多次包含同一个标题)

然而,似乎许多标准 C 库实际上定义了一些东西。让我们以 C 语言中的 stdlib.h 为例。这个库似乎定义了一个名为malloc 的方法来分配内存。但是(当然)如果我在多个文件中包含 stdlib.h,则 malloc 的方法定义似乎没有冲突。

换句话说,如果我要使用自己的内存分配方法创建自己的库(假设它不是宏函数),我将不得不在mylib.h 中声明它并在mylib.c 中实际定义它,但是这个由于某种原因,它似乎不适用于stdlib.h

这是如何工作的?为什么标准 C 库可以做到这一点,而用户定义的标头(不幸的是,在我看来)却不能?

【问题讨论】:

  • 标准库头文件只声明函数。这些函数在库中定义,通常是自动链接的(数学函数除外),但如果您正在为独立环境进行编译,通常可以要求编译器不要这样做。

标签: c class include c-standard-library


【解决方案1】:

标准 C 库已经编译成一个库,可以称为 libc.soMSVCRT100.DLL。您可以提供此文件,而不是编译器将从您的 *.c 文件生成的 *.o*.obj 文件。编译器会自动将此运行时库与每个程序链接。

这也是其他库的工作方式。如果您有已编译的 OpenSSL 库,则链接到该库和源代码中的 #include 头文件以查看其接口,例如函数名称和原型。您不需要构建库的其他源文件。

您可以将源代码下载到 C 库的许多实现中,例如 GNU libc。运行时实际上是在*.c 文件中实现的,您可以对其进行读取、修改、重新编译和向维护者提交补丁,但它会提前编译到共享库,并且您的编译器会链接到该文件。

【讨论】:

  • 三件事:有什么办法可以看到标准C库的源码吗?其次,如果标题 only 包含宏定义,那么跳过创建实现文件是不好的做法吗?第三,是否可以将实现代码以巨型宏的形式存储在头文件中,以便只需在实现文件中使用该宏即可轻松实现该库?在 cmets 中回答这些问题,我会接受你的回答。
  • 这不是提出后续问题的最佳方式,但可以。 1:您可以从 GNU.org 下载一个开源(他们宁愿我称之为 Libre)库,例如 GNU libc。要查看 Microsoft,请申请 Microsoft 的开发工作。
  • 2:我不明白为什么这是一个不好的做法。为什么要创建无用的文件?我有时会制作只包含宏的配置文件。这在 C++ 模板库中更为常见。
  • 3:这是个糟糕的主意。 :) 但仔细思考原因是一个很好的练习。
  • 并非所有的运行时都是用 C 实现的,有些甚至有多个实现。
【解决方案2】:

这是一个老问题,但以后应该有人会遇到这个问题。

我的回答是: stdlib.h不是库。相反,它是一个大库的头文件,它定义了一个名为malloc 的方法来分配内存。

即:

stdlib.h 仅包含其成员的声明(原型)。

库本身(linux-OS 中的<em>.a</em>.so)包含malloc 方法(和其他)的实际定义(实现)。

但这似乎不适用于 stdlib.h 出于某种原因。

确实如此,但唯一的区别是,在您的示例中,您依赖源文件(即mylib.c)来构建库。而在您在问题中使用的标准 C 案例中,如果您包含了它的头文件(即stdlib.h),它已经是一个应该链接到您的程序的库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-11
    • 2023-03-15
    • 1970-01-01
    • 2017-06-06
    • 2021-11-06
    相关资源
    最近更新 更多