我们如果按照上面的展开法进行解释,其实很好理解多个源文件声明#"xxx.h"会导致多个相同的全局变量和函数,这样必然导致重复定义故障,如果小伙伴们不信我直接敲代码看结果:
#include <stdio.h>
#include <stdlib.h>
#include "APP1.h"
#include "APP2.h"
/*********************************************
* Fuction:main
* Author : (公众号:最后一个bug)
********************************************/
int main(int argc, char *argv[]) {
printf("%dn",add_APP1(1,1));
printf("%dn",add_APP2(1,1));
return 0;
}
//Filename:Add.h
/*********************************************
* Fuction:add
* Author : (公众号:最后一个bug)
********************************************/
int add(int a,int b)
{
return (a + b);
}
//Filename:App1.h
int add_APP1(int a,int b);
//Filename:App1.c
#include "Add.h"
/*********************************************
* Fuction:add_APP1
* Author : (公众号:最后一个bug)
********************************************/
int add_APP1(int a,int b)
{
return add(a,b);
}
解析:APP2对应的.c和.h我就不再贴上去了/0在c语言中是什么意思?,毕竟代码比较简单。最后一张图为编译结果,第二行显示重复定义add这个函数。同样作者也进行了对变量一样的做法,同样也是显示的是重复定义相关变量,所以也验证了我们的前面的理论。
2)添加条件编译#
我们大部分小伙伴可能会想我们直接在头文件的函数和变量定义加上条件编译#来避免重复包含不就可以了吗?好了,作者也进行了这个实验大家简单看看代码和结果,后面我来解释下:
//Filename:Add.h
/*********************************************
* Fuction:add
* Author : (公众号:最后一个bug)
********************************************/
#ifndef __ADD_H__
#define __ADD_H__
int add(int a,int b)
{
return (a + b);
}
#endif
解析一下:加了该预编译以后其结果与上一节的结果一致,还是提示重复定义该函数。那是为什么呢?我在前面的《嵌入式编程有道-C语言(1)》中有描述C程序到机器码的一个生成过程,App1.c和App2.c分别编译,然后分别展开#,在最后的链接过程中发现了同名的函数和变量,所以还是会编译不通过。
3)能够帮我们搞定这种窘境
我们都知道表示静态的的意思,也可以说是对变量和函数进行文本上的限制,多个文件中是可以有同名的函数和变量的,不过他们却代表着不同的函数和变量,这一点要尤为注意,如果该头文件在不同文件中大量使用其中的变量和函数也会导致程序的增加和内存的变大,下面作者就为这几点用程序来证明下:
//Filename:Add.h
#ifndef __ADD_H__
#define __ADD_H__
static int add(int a,int b)
{
return (a + b);
}
#endif
//filename:App1.c
#include <stdio.h>
#include "Add.h"
/*********************************************
* Fuction:add_APP1
* Author : (公众号:最后一个bug)
********************************************/
int add_APP1(int a,int b)
{
printf("add_APP1_addFuc:0x%xn",(int*)add);
return add(a,b);
}
解析一下:上面仅仅贴了重要的两段,代码比较简单,我们发现两个里面都是调用的add,但是他们的地址是不相同的,说明他们并不是一个函数。所以大家也可以把Add.h文件用我们模块化设计的思想分为一个.c和一个.h的形式/0在c语言中是什么意思?,最后打印的地址是一样的,代码我就不贴了给大家看一下结果即可,地址是一样的说明他们是同一个函数,同样大伙也可以用修饰变量,也是得到类似的结果。
4、小节
最后小节一下,其实为什么大家一般不在.h文件里面定义变量或者函数其实原因还有很多,最主要的是不符合相关设计要求,比如进行代码上的改动话,编译会造成连锁反应导致编译时间再次编译时间较长等问题,同时代码上的分析比较麻烦,所以大家对于这类问题其实也是可以平时闲暇时候好好研究一下,同时你会在其中收获很多意外的知识点,要做到"知其然而知其所以然",其实在头文件中定义函数或者变量并不是没有这样的设计需求,大家可以考虑一下在头文件中定义的这种使用有缺点,是否会有什么优点呢?哈哈,这里我就不揭秘了,请听下回分解!