【问题标题】:extern function in header file vs source file头文件与源文件中的外部函数
【发布时间】:2015-02-13 11:45:57
【问题描述】:

我有这个 C 编译问题。

我花了一段时间才了解问题的根本原因。 虽然,现在我已经截获了这个问题,但我不确定我是否完全低估了完整的 C 编译流程逻辑。

我有两个目录:inc 和 src

在 inc 目录中,我有一个文件:test.h 在 src 目录中,我有两个文件:test.c 和 main.c

test.c文件实现了一个函数,我们称之为test(),main.c文件调用这个test()函数。

我在 test.h 文件中声明了这个函数

现在,我只在 main.c 文件中包含了这个 test.h 文件,以便让 main.c 文件“看到” test() 函数的声明。

编译时:

g++ -o test.o -c test.c
g++ -o main.o -c main.c
g++ -o test test.o main.o

在最后一个命令中,我收到“未定义对 'test' 的引用”的错误

调试了这个问题,发现test.c文件中缺少test.h文件的include解决了这个问题。

换句话说,我需要在两个源文件 - main.c 和 test.c 中包含 test.h 文件

我的问题是,为什么? 仅在 main.c 文件中包含头文件 test.h 文件是否不够,以便让它“看到”函数声明,并且在链接阶段编译器会“知道”关联 test( ) main.c 文件中使用的函数要在 test.c 文件中实现吗?

我认为 test.h 文件中的 test() 函数的声明使其成为“外部”声明,因此它会通知编译器在链接阶段找到函数实现

【问题讨论】:

  • 预处理器在#include 指令的位置完全包含包含文件的内容。这意味着只有包含特定头文件的源文件才会知道头文件中的声明。包含所有头文件的源文件称为translation unit,每个翻译单元或多或少是独立的。
  • 即使您test.c 中不包含test.h 导致编译失败,编译器也无法检查test() test.h 中的函数原型是正确的:编译器和链接器都不会知道您是使用不正确的参数调用 test(),还是使用不正确的返回值。
  • 没有看到声明和定义,很难猜测出了什么问题。这可能与使用 C++ 编译器编译看似 C 程序的内容有关。为什么要这么做?为什么这个问题会被标记为两种语言?
  • 请张贴(相关部分)文件,以便我们查看声明和定义。
  • 只要test.h 中的test 函数声明与test.c 中的定义匹配,这应该可以正常编译和链接。

标签: c++ c


【解决方案1】:

问题是因为您的原型与实现不匹配。

如果您使用 C 编译器,由于错误的参数和返回值处理,您会遇到有趣的运行时错误,因为生成的符号通常不包含参数信息。

使用 C++,编译器会根据参数类型生成方法签名。所以两个同名但参数不同的函数会产生两个不同的符号,所以链接器不会混淆它们。

所以修复你的原型,它会工作的......

【讨论】:

    【解决方案2】:

    我认为只在 main.c 中添加 test.h 而不是在 test.c 中应该没有任何问题。请再次检查您的设置。

    您可以在test.h 中声明该函数并将test.h 包含在main.c

    或在main.c 本身中将函数声明为extern。 在这两种方式中,链接器都必须完成查找 test() 定义的工作

    包含文件通常用于将接口与实现分开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 2014-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多