【问题标题】:C - Why can I use a function from another source file without including the source file?C - 为什么我可以使用另一个源文件中的函数而不包括源文件?
【发布时间】:2015-12-15 09:57:36
【问题描述】:

早安,

我拥有的是以下内容:

//Simulator.h
#ifndef SIMULATOR_H
#define SIMULATOR_H

inline void functionn1(void);
#endif

然后我有它的实现:

//Simulator.c
#include <stdio.h>
#include <stdlib.h>
#include "simulator.h"

inline void functionn1(void){printf("Functionn 1\n");}

最后是主程序:

//main.c
#include <stdio.h>
#include <stdlib.h>
#include "simulator.h"

int main(int argc, char** argv) 
{
functionn1();
return (EXIT_SUCCESS);
}

它按预期工作,但在玩过之后我注意到:

  1. 当我从 Simulator.h 中注释掉函数原型时,它也可以工作
  2. 此外,当我注释掉函数原型并且故意不在 main.c 中包含 Simulator.h 时,该函数仍然有效。

为什么我做了上述两个步骤后它会起作用?这里到底在搞什么恶作剧?

【问题讨论】:

  • 你试过用 -Wall 选项编译吗?它会给你warning: implicit declaration of function
  • 如果您使用的是相当新的标准,例如 C99,它应该不再适用。当你写“functionn3”时,你的意思是functionn1,不是吗?
  • 因为您实际上是在调用 functionn3() 。 functionn1 的定义无关紧要。
  • @LPs - 我正在使用 NetBeans IDE
  • @MOehm - 是的,我的意思是 functionn1 这是一个错字

标签: c function include header-files


【解决方案1】:

当 C 解析器遇到一个函数用法并且它对这个函数一无所知时,它会生成一个虚拟签名并继续。

链接器将尝试找到适当的符号(即在传递给链接器的任何代码对象/库中查找具有函数名称的符号),这似乎存在于您的案例中。

您通常会收到警告,因为它可能会导致几个错误:假定自动生成的函数返回一个 int。如果实际返回了一个指针并且sizeof(int) != sizeof(intptr_t) 你会得到一个微妙的错误,因为地址将被截断。

例如下面的编译

int main(int argc, char**argv) {
  return foo();
}

(如果foo 未在另一个编译单元中定义,则可能会遇到链接器错误),但以下内容不编译:

struct test {};
// missing declaration:
// struct test foo();
int main(int argc, char**argv) {
  // foo is not available, it defaults to returning an int
  struct test t = foo();
  return 0;
}

因为从隐式返回类型int 到struct test 的转换无效。

【讨论】:

  • 我明白你在说什么,但我不明白你的最后一个结构示例是要传达什么 - 它不起作用,因为你在尝试分配返回值时遇到了真正的语法错误从一个函数到你的空结构,这有什么关系?
  • @ShadyProgrammer :假设foo 返回struct test。由于声明不可用,因此默认为返回 int 的函数,这是不正确的;我已经更新了代码以显示这一点。
【解决方案2】:

由于历史原因,C 也可以在没有任何函数原型的情况下工作。缺点是不会有参数检查。

只要有导出函数的目标文件,链接器就会知道如何将各个部分组合在一起。

【讨论】:

  • 阅读您的回答后,我做了一些研究,发现使用关键字 static 可以防止我原来问题中的行为,这是否是最优化的方法?做吗?
  • 是的,没错。如果你在 C 中声明一个静态函数,它只会在定义它的源文件中知道。
猜你喜欢
  • 2020-10-24
  • 1970-01-01
  • 2014-11-18
  • 2010-09-18
  • 1970-01-01
  • 2015-09-09
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
相关资源
最近更新 更多