声明与定义的区别 - 范文中心

声明与定义的区别

12/29

什么是声明,什么又是定义?

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

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

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关键字(即使不加也可以,但务必要加上),同样,如果一个全局变量不是定义在文件的开头而是中间的话,在其同文件前面的函数要引用它也同样要遵循此做法,以免造成不必要的麻烦。 好了,现在的你,是否对声明和定义的区别有了稍微深一点的理解了呢?啊,竟然还不懂,没关系没关系,可能是我讲得不够好,欢迎有兴趣的童鞋共同讨论讨论!

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


相关内容

  • VHDL语言中的信号.变量与常量异同比较
    VHDL语言中的信号.变量与常量异同比较 在VHDL中,对象是指用来保持数据的一些客体单元.VHDL中的对象主要有4种:常量(CONSTANT).变量(VARIABLE).信号(SIGNAL)和文件(FILE).本文主要讨论前面三种在实际应 ...
  • 嵌入式经典面试题
    嵌入式经典面试题六: 关键字static的作用是什么? 这个简单的问题很少有人能回答完全.在C语言中,关键字static有三个明显的作用: 1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变. 2) 在模块内(但在函数体 ...
  • C语言源程序
    C 语言程序设计 C 语言程序设计 1.程序运行从main()函数开始,也从main()函数结束. 2.函数是C 程序的,. 3.C 语言源程序是由函数组成,它们. 4.在C 语言源程序中,是必须有一个函数名为main 的函数.main() ...
  • MTK软件的有关面试题
    1.在屏幕上写Hello World 2.用c语言怎样编写:在1到20随机产生5个不相同的数 3.不调用C++/C的字符串函数,请编写函数strcpy 4.解释char *const p=在编译时分配的区间,执行过程中不自动释放会记住上次执 ...
  • 招商银行培训材料(新员工)
    保函 保函的定义 保函的作用 保函的性质 保函的当事人及其权责 保函的种类及功能 保证和保函的区别 保函的办理 保函与备用信用证的比较 保函的定义 保函(Letter of Guarantee, L/G)又称保证书,是指银行.保险公司.担保 ...
  • 专门化 DITA 主题类型
    中国 [选择] 使用条款 dW 全部内容----------------- AIX and UNIX Information management Lotus Rational Tivoli WebSphere Workplace----- ...
  • 常量与变量的分类
    整型常量 1. 八进制整常数 八进制整常数必须以0开头,即以0作为八进制数的前缀.数码取值为0-7.八进制数通常是无符号数. 以下各数是合法的八进制数: 015(十进制为13) 0101(十进制为65) 0177777(十进制为65535) ...
  • java基础笔试测试题及答案
    Java 一章 至 五章 考试 一. 填空题(8分) 1. 面向对象的三大原则是( 封装 ),( 继承 )和( 多态 ).2分 2. 如果想在对象实例化的同时就初始化成员属性,则使用( 构造函数 ).2分 3. ( 实体) 方法和( 构造 ...
  • 联通笔试题
    选择题 1.通信网的基本结构形式有五种,以下正确的说法是(C) A.网型.星型.树型.环型.总线型: B.网型.星型.线型.复合型.环型: C.网型.星型.复合型.环型.总线型: D.网型.环型.线型.复合型.树型. 2.N个节点完全互联的 ...
  • 个人信用报告解读 [非常详细 | 银行天地 - 东方论坛
    个人信用报告解读 [非常详细  0点 一.信用报告中的"查询时间"和"报告时间"有什么区别? 信用报告中显示的"查询时间"是指系统收到查询者提出查询请求的时间:"报告时间 ...