【问题标题】:Linking object files, making include redundant?链接目标文件,使包含冗余?
【发布时间】:2010-11-01 17:02:05
【问题描述】:

我正在尝试一点 C。我以为我已经理解了这个链接业务。但我想不会。我有一个简单的文件 main.c:

#include "function.h"
int main(char args[])
{
    int print = myfunction();
}

然后是第二对文件 function.c/function.h

int myfunction(); //function.h

int myfunction()  //function.c
{
    return 5;
}

编译这个效果很好。但是,无论我是否在主文件中使用#include "function.h",它都可以正常工作。那我为什么需要包含 function.h 呢?

【问题讨论】:

  • 顺便说一下,main 的参数应该是 (int argc, char* argv[]) 或者可能是 (void),而不是 (char args[])

标签: c linker compilation object-files


【解决方案1】:

我不知道你使用的是什么系统,但如果它使用 gcc 或其他兼容的系统,请再试一次

cc -Wall -Werror *.c

或者,为您的系统打开等效选项。

大型程序总是以这种方式构建,以便编译器检查参数类型。与动态和脚本语言不同,C 生成实际的机器代码,并且在运行时不检查参数计数或兼容性。

因此,函数原型被添加到基础语言中,以便在编译时进行类型检查。它们是可选的。

【讨论】:

  • 来自 GCC 的相关警告是:main.c:4:5: warning: implicit declaration of function 'myfunction' [-Wimplicit-function-declaration]
【解决方案2】:

C 编译器不要求您在使用函数之前为函数指定原型1。原型只是让编译器验证您传递的参数的类型是否与函数所需的类型相匹配——如果不正确,则隐式转换为正确的类型,并且存在隐式转换从/到所涉及的类型。

只要您的代码是完美的,并且您使用函数的方式与该函数的预期使用方式之间没有不匹配,您就不会有问题。在您的测试中,您有一个不带参数并返回一个 int 的函数,而使用它的代码基本上什么都不做。这种情况很难搞砸,而且效果很好。在具有数百或数千个函数的实际程序中,采用复杂类型的多个参数等,情况变化很快。让编译器确保您正确调用函数变得非常更加重要。

1除了可变参数函数,即使是“可变”参数也基本上遵循相同的规则,就好像没有函数原型一样。

【讨论】:

  • 很多详尽的答案,但你是彻底和快速的......接受!
  • 吹毛求疵:如果返回类型不是 int(浮点结果通常在另一个寄存器中返回而不是整数),则需要声明,如果有任何参数可以提升( type char, short) 和可变参数函数(它们可能有另一个 ABI,而不是普通函数,留给调用者清理堆栈的任务,而不是例如弹出参数)。
【解决方案3】:

当您使用尚未定义的函数时,许多 C 编译器只会假定它是一个返回 int 的 extern 函数(您经常会收到警告,但代码会编译。)您会遇到问题不过,请开始使用具有更复杂参数和返回类型的函数。

【讨论】:

    【解决方案4】:

    如果您使用未声明的函数,较旧的 C 编译器将假定它具有参数 ... 和返回类型 int。不建议这样做。如果您打开编译器警告,您可能会收到有关使用未声明函数的警告。如果编译器在编译 main.c 之前看到 function.h,则编译器可以捕获更多错误,因此它确切地知道 myfunction 应该如何操作。

    【讨论】:

      【解决方案5】:

      您在头文件中声明一个函数以在不同的模块中使用它。您不一定需要源代码。您可以链接到二进制库。在编译期间,您需要声明用于检查参数、类型等的方法。

      在您的简单示例中,这不是必需的。

      【讨论】:

        猜你喜欢
        • 2011-03-05
        • 1970-01-01
        • 2016-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-16
        相关资源
        最近更新 更多