user-0 提问: 关于include的一个困惑

回复:
user: user-1
content: 既然函数是库中的，你调用该函数的文件必须要做该函数的申明（库文件都是伴随有.h文件的，不然你咋知道这个库有哪些函数，函数原型是什么。这里把申明该函数的.h文件include到你文件中）。然后，将该函数所在文件加入到你的工程中（有的是.o文件，有的是dll文件等等，怎么添加看你的编译器而定）。  有的库是以源码形式提供的，这个你应该知道怎么搞。

user: user-2
content: a.c和main.c是不同的编译单元。 编译器编译的时候，是先编译每一个编译单元，生成各个单元的链接文件（即a.o main.o），再用链接器链接成可执行文件。  a.c编译成a.o时，当然找不到func1的定义拉。

user: user-3
content: 引用 10 楼 e08610318 的回复:[quote=引用 9 楼 s_a_n_ 的回复:] 编译的时候只需要有函数的声明就可以调用该函数，编译成功。 连接的时候需要找到该函数的定义，就是具体调用的什么东东要知道。 你没有添加定义的时候只有声明因此只能编译通过的，连接的时候找不到函数定义。 举个例子，老大让你找一个叫小明的人帮你忙，可是你只知道他的名字（函数声明）却不知道他在哪里（函数定义，即函数体的起始位置），你怎么让他帮你的忙呢  能否调用一个函数与函数在哪个文件中定义无关。 在哪个文件中定义，只是影响了声明函数的方式。  总结一下：凡是你调用到的函数，都必须有明确的定义。如果你没有定义一个函数，那么就不能调用它。  你的意思是，只要一个文件包含了需要调用的函数的声明，那么该函数的定义放在哪都没关系？[/quote] 对，不过有一点需要说明的是，被调用的函数定义必须存在（通常放在同一个工程下参与编译即可）。 放在某个.c源文件中经过编译生成目标代码也可以，使用动态/静态链接库也可以。

user: user-4
content: 应该是链接错误吧

user: user-0
content: 引用 9 楼 s_a_n_ 的回复:编译的时候只需要有函数的声明就可以调用该函数，编译成功。 连接的时候需要找到该函数的定义，就是具体调用的什么东东要知道。 你没有添加定义的时候只有声明因此只能编译通过的，连接的时候找不到函数定义。 举个例子，老大让你找一个叫小明的人帮你忙，可是你只知道他的名字（函数声明）却不知道他在哪里（函数定义，即函数体的起始位置），你怎么让他帮你的忙呢  能否调用一个函数与函数在哪个文件中定义无关。 在哪个文件中定义，只是影响了声明函数的方式。  总结一下：凡是你调用到的函数，都必须有明确的定义。如果你没有定义一个函数，那么就不能调用它。  你的意思是，只要一个文件包含了需要调用的函数的声明，那么该函数的定义放在哪都没关系？

user: user-3
content: 编译的时候只需要有函数的声明就可以调用该函数，编译成功。 连接的时候需要找到该函数的定义，就是具体调用的什么东东要知道。 你没有添加定义的时候只有声明因此只能编译通过的，连接的时候找不到函数定义。 举个例子，老大让你找一个叫小明的人帮你忙，可是你只知道他的名字（函数声明）却不知道他在哪里（函数定义，即函数体的起始位置），你怎么让他帮你的忙呢  能否调用一个函数与函数在哪个文件中定义无关。 在哪个文件中定义，只是影响了声明函数的方式。  总结一下：凡是你调用到的函数，都必须有明确的定义。如果你没有定义一个函数，那么就不能调用它。

user: user-5
content: 引用 3 楼 e08610318 的回复:[quote=引用 1 楼 wangzuxi 的回复:] [quote=引用 楼主 e08610318 的回复:] 描述：          config.h文件声明了一个全局函数func1，且只包含了一个类型定义的H文件，main.c只包含config.h，此外工程中包含了文件a.c，但是没有用到a.c的函数，但a.c要用到全局函数func1，此时编译出错，告知找不到func1的定义，然后在main.c定义了func1函数，编译通过。这是怎么回事？  引用：这是我在使用CMSIS固件库时遇到的问题，此时func1对应void check_failed(uint8_t *file, uint32_t line)。 a.c用到了func1，但func1没有定义，当然出错，之后你在main.c中定义了func1，在编译a.c编译器在main.o中找到了func1的定义，所以能编译通过。[/quote] 这个我也知道，能从文件包含的一些机制来回答该问题吗？比如说编译器在编译过程中它的依赖关系是怎么建立的？主要是这个做法不是通用做法，一下子我就反应不过来了。[/quote] 推荐你看看这篇文章： http://codemacro.com/2014/09/15/inside-static-library/

user: user-0
content: 引用 2 楼 JiangWenjie2014 的回复:那就把a.c从工程中移除啊，否则的话，a.c需要使用func1，那么在链接阶段函数func1必须是有定义的。  这个治标不治本的，以后要用到呢？所以我事先在工程中加入了该文件。

user: user-0
content: 引用 1 楼 wangzuxi 的回复:[quote=引用 楼主 e08610318 的回复:] 描述：          config.h文件声明了一个全局函数func1，且只包含了一个类型定义的H文件，main.c只包含config.h，此外工程中包含了文件a.c，但是没有用到a.c的函数，但a.c要用到全局函数func1，此时编译出错，告知找不到func1的定义，然后在main.c定义了func1函数，编译通过。这是怎么回事？  引用：这是我在使用CMSIS固件库时遇到的问题，此时func1对应void check_failed(uint8_t *file, uint32_t line)。 a.c用到了func1，但func1没有定义，当然出错，之后你在main.c中定义了func1，在编译a.c编译器在main.o中找到了func1的定义，所以能编译通过。[/quote] 这个我也知道，能从文件包含的一些机制来回答该问题吗？比如说编译器在编译过程中它的依赖关系是怎么建立的？主要是这个做法不是通用做法，一下子我就反应不过来了。

user: user-6
content: 那就把a.c从工程中移除啊，否则的话，a.c需要使用func1，那么在链接阶段函数func1必须是有定义的。

user: user-5
content: 引用 楼主 e08610318 的回复:描述：          config.h文件声明了一个全局函数func1，且只包含了一个类型定义的H文件，main.c只包含config.h，此外工程中包含了文件a.c，但是没有用到a.c的函数，但a.c要用到全局函数func1，此时编译出错，告知找不到func1的定义，然后在main.c定义了func1函数，编译通过。这是怎么回事？  引用：这是我在使用CMSIS固件库时遇到的问题，此时func1对应void check_failed(uint8_t *file, uint32_t line)。 a.c用到了func1，但func1没有定义，当然出错，之后你在main.c中定义了func1，在编译a.c编译器在main.o中找到了func1的定义，所以能编译通过。

user: user-7
content: 在a.c中加入extern void check_failed(uint8_t *file, uint32_t line)或者包含config.h头文件

user: user-8
content: include实际就是代码替换，把include文件里所有的内容copy过来。  --------万恶的分割线-------------------------------------------------------------  编译阶段：     1.  include和宏替换。     2.  把所有声明的函数解释成编译器能识别的函数别。(有可能是fdff@check_failed，这样看起来很乱的函数名，也有可能是汇编码)。     3.  把所有的代码，所有的函数调用，全部关联到函数定义的地方。(如果没有找到，此时就会报错)。  以上是我的粗浅的理解。。。。

user: user-9
content: a.c也包含 config.h啊