视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
声明与定义的区别
2025-09-28 20:03:22 责编:小OO
文档
什么是声明,什么又是定义?

相信很多人都问过自己或别人这样的问题。今天,我就发表一下我个人的一点小见解,希望对这两者有疑问的童鞋能理清他们的关系。

理解两者的区别之前,你要重新整理一下一些概念:

1.C语言的对象,不管是什么,变量也好,函数也罢,他们都有且只能有一个定义,而声明却不同,理论上,只要你愿意,他们可以有任意多个声明,这就是为什么形如extern xxx xxx;能被同时包含到不同的头文件的原因(因为它是声明啊,彩旗飘飘,你懂的)

2.声明只是告诉编译器说:“喂,编译器老兄啊,我是某某某的影子,你要找到他的话(编译时用到)去别处找啊,我只是他的影子哦”,所以请记住,声明时编译器并不会为声明的对象分配内存(有内存的话就不会是影子了,是吧),而定义时编译器会为定义的对象分配内存。

可能有人会问:那下面这种情况下哪一个是声明哪一个是定义啊???

 

       

其实上面两个都是变量i的声明,他们会最终被保留在可执行文件的BSS段,编译器不会为其分配内存,可能又有人会问:“未初始化的全局变量不是都被编译器隐式地初始化为0吗,他们既然被隐式初始化为0,那也应该有相应的内存地址啊,怎么会都是声明呢?”有这样问题的童鞋很好,说明你已经对声明和定义的区别有所掌握了,不过事实是怎样的呢?事实上编译器不会为BSS段的数据(即未初始化的全局变量)分配内存,只是在BSS段上保留相应未初始化全局变量类型和名字的信息,好让系统运行可执行文件时能给未初始化全局变量分配内存并初始化为0。所以呢,现在清楚了吧,未初始化全局变量是在程序执行时才真正被初始化的,故上面两个都是对量i的声明,而且声明的是同一个i(同一个内存地址),虽然说这样写编译器能接受,但是我强烈建议不要这样写,这是C语言的一个灰色地带,这样会给人感觉是两个变量,而其实他们是同一个,这样只会造成没必要的麻烦,也会让你将来维护这个程序时发疯的,如何避免命名冲突呢?对于其他文件不用引用到的全局变量,我们可以在定义全局变量时在类型名前面加上static关键字来避免命名冲突问题。

倘若是下面这种情况呢:

            

       

在这种情况下,第一个文件的是定义,第二个文件的是声明,因为缺省情况下int i跟extern int i是一样的(就是说关键字extern可以省略不写),这同样可能误导别人,例如,我们都知道未初始化的全局变量系统执行时会给它初始化为0,如果我们不知道文件2的 int i其实是文件i声明时就有可能出事,我们会认为文件2的i被系统初始化为0,假如我们把自认为是0的i赋值给别的变量就有可能出现意想不到的bug,所以呢,也请不要这样写,即使你自己知道文件2中int i是对文件1中i的声明(但你能保证维护你代码的人知道吗)。

好像还有一种情况:

    

呵呵,其实这样是错误的,为什么呢,很简单,两个都是定义,所以编译器会抱怨:“喂,我,这样我怎么编译啊,重定义啊你”。

所以呢,为了解决上面种种情况,我们要保证只在一个文件中出现对一个全局变量的定义,其他文件想引用此变量必须加上extern关键字(即使不加也可以,但务必要加上),同样,如果一个全局变量不是定义在文件的开头而是中间的话,在其同文件前面的函数要引用它也同样要遵循此做法,以免造成不必要的麻烦。

好了,现在的你,是否对声明和定义的区别有了稍微深一点的理解了呢?啊,竟然还不懂,没关系没关系,可能是我讲得不够好,欢迎有兴趣的童鞋共同讨论讨论!

此文是我的一点小小的见解,如果错误的地方还请各位大牛指正,万分感激啊。下载本文

显示全文
专题