在源文件(.c)和头文件(.h)中声明和定义的区别——C语言

最近在看多文件编程的时候遇到的一个问题,本来以为理解了声明和定义的区别(然而并没有····),也算是重新认识了一次声明和定义,下面上代码

 

声明和定义:有分配空间的叫定义,没分配空间的叫声明

定义:表示创建变量或分配存储单元

声明:说明变量的性质,但并不分配存储单元

 

情形一:在源文件(.c)中(函数内)

int a;//定义
extern int a;//声明

第一个int a是定义,分配了存储空间(其实包括了声明和定义两个步骤,可以叫"定义性声明"),第二个 extern int a是声明(也叫"引用性声明"),没有分配存储空间

关于extern的使用,感兴趣的读者可以看一下另一片随笔:extern的使用详解(多文件编程)——C语言

 

声明可以多次,定义只能有一次

意思是在源文件(.c)中可以多次声明同一个变量,例如在编译阶段是不会报错的

 

情形二:在源文件(.c)中(函数外)

编译结果:

这里的int a;放在函数外,没有出现重定义的错误,并不意味着int a就不是定义了,int a仍然是定义,编译阶段没有报错了原因在于全局变量没有赋初值,没赋初值的全局变量,那么在目标文件中是不会为

这个全局变量分配空间的,它被放在BSS段(如果是赋初值的全局变量,那么放在data段),BSS段在目标文件中是没有的(这个就是编译阶段不会报错的原因),意味着没赋初值的全局变量不占磁盘空间,

当程序加载运行时,就会为bss段中的数据分配内存进行初始化(起到了节省磁盘空间的作用),上面说了BSS段的数据不占磁盘空间,那么它的大小和符号存在哪呢? bss段占据的大小存放在ELF文件格式

中的段表(Section Table)中,段表存放了各个段的各种信息,比如段的名字、段的类型、段在elf文件中的偏移、段的大小等信息

(感谢园友:SD8086 指出随笔中的错误)

(对内存映像感兴趣的读者可以看下这两篇文章:bss段不占据磁盘空间的理解大内高手—全局内存

 

情形三:在头文件(.h)中

在头文件中的声明和定义和在源文件中函数外的声明和定义相同,下面为测试结果

修改头文件后

从上面可以看出int a在头文件中仍然是定义,只不过和全局变量定义相同,只要没有赋初值,编译阶段就不会报错

posted @ 2019-04-11 21:47  Luv3  阅读(21632)  评论(3编辑  收藏  举报