定义 & 声明

来源:互联网 发布:jsp中调用java方法 编辑:程序博客网 时间:2024/04/30 17:12
        近来思绪比较凌乱,于是想写点什么来寄托空虚寂寞之情怀,支撑自己孤苦无助的人生。但是又不想写鸡汤,那么,我们来聊聊“声明”和“定义”吧。

        先来提个问题:为什么每次圣斗士出招之前都要大喊一下招式?

嗯,没错!因为函数要先声明,然后才能调用。

举个栗子:

我们定义了一个这样子的函数 -->

int function (int person1, int person2){      // palapala …}

那么,一般我们会在头文件中做这样子的声明 -->

int function (int person1, int person2);

那么,问题来了:为什么需要声明?

        (砖家来了)因为C/C++是强类型的语言,如果不声明就使用,在一个编译单元中,编译器没有办法判断使用是否合法,如参数个数、参数类型匹配等等,这样强类型就难以实现。

        这是一个大神说了算的世界,不服你来写个编译器啊!

有些小朋友可能会说:“谁说函数要先声明才能调用的?我没有声明一样可以调用呀,不信你看!”

void sayHello(){        cout<<"hello"<<endl;}int main(){        sayHello();}

        (砖家又来了)这位小朋友你是猪啊?!都叫你别看那么多暴走漫画喽,这是声明和定义放在一起了,而且是在main函数前面,所以编译器不会报错。顺便简单提一下:声明在编译期确定,定义在运行期确定。

        下面再说一下变量的声明和定义,据说这个重要的概念在大学里从来没有被提起过,不管你信不信,反正我大学那会真的木有老湿跟我讲过。(这是一个沉重的话题,略过。。。)

        大家打起精神,我们一起探讨:

What is 定义?——所谓的定义就是编译器创建一个对象,为这个对象分配一块内存并给它取上一个名字,这个名字就是我们所说的变量名/对象名。这个名字一旦和这块内存匹配起来,它们就同生共死,终生不离不弃(好浪漫,正所谓:执子之手,与子偕老),并且这块内存的位置也不能被改变。一个变量或对象在一定区域内(涉及作用域和生命周期)只能被定义一次,如果定义多次,编译器会提示你重复定义同一个变量或对象。

What is 声明?——告诉编译器,这个名字已经匹配到一块内存上了,所以你不能再用它作为你将定义的变量名/对象名(可爱的白菜已经被可恶的猪给拱了,没办法,谁叫你腿短),下面代码中出现的变量或对象在别的地方定义了,需要明确,声明是可以出现多次的(想象一下圣斗士喊了N多次才出大招 -_-#)。

        所以,定义和声明最重要的区别在于,定义创建了对象并为这个对象分配了内存,声明没有分配内存(不管是黑猪还是白猪,有白菜的猪才是幸福的猪)。

        细心的小朋友可能已经想到,对于局部变量来说,这种变量的声明再使用是很少出错的,关键是变量作为全局变量的时候所带来的一些困扰。

        说到这,就不得不提staticextern这两个关键字了。static的几种用法就不多说了,这里提醒!如果想让你的全局变量能用于多个文件,一定不要加static啊。

        (砖家悄悄地出现了)众所周知,全局变量应该是得到内存分配且可以被其他模块通过extern调用的变量。因此,必须在.c.h文件中声明,但是这种重复的声明很容易导致错误。

栗子来了:

        假设在一个.c文件里定义全局变量aint a;,然后在它的头文件声明了:extern int a;然后有另一个.c文件在使用变量a的时候觉得double会更好,然后就声明了:extern double a;,但是又没有把所有类型改过来,于是就出大事了!

        这就是为什么重复声明容易导致错误。这时候,大神头上的灯泡亮了,说:“只声明一次不就完了嘛”。

        对,这就是这篇文章的重点,大家看好了!

在头文件中定义全局宏:

#ifdef xxx_GLOBALS#define xxx_EXT#else#define xxx_EXTextern#endif

        为.h文件中每个全局变量都加上xxx_EXT的前缀。xxx代表模块的名字,然后在该模块的.c文件中定义:#definexxx_GLOBALS

        当编译器处理.c文件时,它强制xxx_EXT为空(因为xxx_GLOBALS已经定义),所以编译器会为全局变量分配内存空间。而其他的.c文件,由于xxx_GLOBALS没有定义,所以xxx_EXT被定义为extern,这样用户就可以调用外部全局变量了。

        哇咔咔,大神果然是大神。

        又有捣蛋的小朋友出来了,说:“既然上面出现的问题是由于把int改为double而导致的,那么干脆就不要写变量类型呗”。

        没错,这位小朋友很聪明,声明时直接写:extern a;也是可以的。但是写上类型会更合理,因为你不是一个人在战斗啊,在团队协作项目中,很多时候你所参与的只是其中某些模块,所以,你懂的!

        而且上面只声明一次的做法真的是很方便嗲*^_^*

 

好哒,写到这里就要告一段落了。相信能看到这里的,都是和我一样即使生活再苦逼但内心依然充满希望的单身狗。

如果这篇文章能让你进一步理解声明和定义,那么我很高兴,请叫我红领巾,不谢。

如果对文章的内容有任何疑义,请不要来找我,我只想静静地做个美男子。 

1 0