C - 为什么我可以在不包含源文件的情况下使用其他源文件中的函数?

时间:2015-09-18 09:41:39

标签: c function include header-files

早上好,

我所拥有的是以下内容:

//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时,该函数仍然有效。
  3. 为什么在我执行上述两个步骤后它才有效?什么样的shennanigans在这里?

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

当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;
}

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