C语言中声明与定义
声明指定了一个变量的标识符,描述了一个变量的类型。
声明用于编译器识别变量名所引用的实体。
以下是一些声明:
extern int bar;
extern int g(int,int);
double f(int,double); //对于函数声明,extern关键字可以省略
class foo; //对于类的声明
定义是对声明的实现或者实例化。
连接器需要定义来引用内存实体。
以下是一些定义:
int bar;
int g(int lhs,int rhs){
return lhs*rhs;
}
double f(int I,double d){
return i+d;
}
class foo{
};
定义是只能做一次的。
声明是可以多次的。
如下多次声明完全ok:
#include <stdio.h>
#include <stdlib.h>
int my_add(int a, int b);
int my_add(int a, int b);
int my_add(int a, int b);
int main(int argc, char *argv[]) {
printf("%d\n",my_add(5,6));
return 0;
}
int my_add(int a, int b){
return a+b;
}
如果你忘了定义一些你已经声明过的变量,或者忘了定义一些你在某些地方被引用到的变量,
那么连接器linker是不知道这些引用该连接到哪块内存上的,然后就会报missing symbols 这样的错误。
如果你定义变量超过一次,连接器linker是不知道把引用和哪块内存连接,然后就会报duplicated symbols这样的错误了。
以上的symbols其实就是指定义后的变量名,也就是其标识的内存块。
例如,忘记定义已经声明过的函数:
#include <stdio.h>
#include <stdlib.h>
int my_add(int a,int b);
int main(){
printf("%d\n",my_add(5,6));
return 0;
}
在编译阶段一切ok,因为声明是给编译器看的,有声明就能过。
但实际在连接的时候,linker会去寻找这个声明的实现,也就是定义的那部分,发现没有,就报“unresolved external symbol _my_add”的错误(missing symbols)。
如果只是为了给编译器提供引用标识,让编译器能够知道有这个引用,能用这个引用来引用某个实体(但没有为实体分配具体内存块的过程)叫做声明。
如果该操作能够为引用指定一块特定的内存,使得该引用能够在link阶段唯一正确地对应一块内存,这样的操作叫“定义”。
声明是为了让编译器正确处理对声明变量和函数的引用。定义是一个给变量分配内存的过程,或者是说明一个函数具体干什么用。
声明包含定义。
比如:int a;
当声明类型是int名字是a的变量的同时我们也定义了a这个变量(在内存中的某部分)。
注意:声明包含定义,也可能不包含定义。Int a就是声明包含定义,但是诸如extern int a;则仅仅是声明,没有定义。
可以使用extern关键字声明变量名但是不定义它。
比如:extern int i; 仅仅对i进行了声明但实际上没有定义i。
比如:int i; 既进行了声明也进行了定义。
例如:
#include <stdio.h>
#include <stdlib.h>
int main(){
extern int i;
i = 5;
return 0;
}
在连接的时候会报错。
extern int i;只是说明(声明)变量在程序其他地方定义(也就是程序的外部,一般是程序的其他文件中),
但是程序找不到i的定义(linker不知道该把i和内存中的哪一个区域关联起来,也即指针不知道该指向哪个地址),所以报错。
Extern只是声明,不是定义,不会分配内存空间。
Right code:
#include <stdio.h>
#include <stdlib.h>
extern int i = 5;
int main(){
return 0;
}
Right code中定义了i,分配并且初始化了存储空间。
但是,只有当extern声明位于函数外部时,才可以含有初始化式(才能进行初始化)。
Error code:
#include <stdio.h>
#include <stdlib.h>
int main(){
extern int i = 5;
return 0;
}
Error information:error C2205: 'i' : cannot initialize extern variables with block scope(块范围)
Right code:
#include <stdio.h>
#include <stdlib.h>
int main(){
extern int i;
i = 5;
printf("%d\n",i);
return 0;
}
int i;
Error code(如果把main中的extern去掉的话):
#include <stdio.h>
#include <stdlib.h>
int main(){
i = 5;
printf("%d\n",i);
return 0;
}
int i;
Error information: error C2065: 'i' : undeclared identifier
Other Right Code:
#include <stdio.h>
#include <stdlib.h>
int main(){
extern i;
i = 5;
printf("%d\n",i);
return 0;
}
int i;
对于Other Right Code的解释:声明外部变量(全局变量)时可以把变量类型去掉如:extern A;
资料来源:
1. http://jingyan.baidu.com/article/020278118e51e01bcd9ce576.html
2. http://blog.sina.com.cn/s/blog_755f0c2401012im8.html
3. http://jingyan.baidu.com/article/37bce2be3d92f11002f3a2fc.html
4. http://bbs.chinaunix.net/thread-4184481-1-1.html
5. http://www.cnblogs.com/haore147/p/3647466.html
6. http://zhidao.baidu.com/link?url=JzQE0FOvo0ngPPIfo4TmcEs6myJrif_GrQVRAMt5uwPCSiH-MsZIRwMWEe7ckymk0y4DnVLL7wX6VytmTZhVrq
7. http://zhidao.baidu.com/link?url=E1HrVjyeeoBc2ZTdbmp0lw_phwGJ6sz2PKejRkHdDms-1P7TatAUUPuYMEw-QYYLhmgO7TuI83WozASaL3X5vQN0sNQKfQ3GePkeV4PGbXC
8. http://blog.youkuaiyun.com/sjxbf/article/details/6310150
9. http://wenku.baidu.com/link?url=u5XXkZ8M8Dt0nx9XPAR-rp82PFhGDFJsHed6-mMSPN-fhr5MG_emD6WXFOcVxJiBsYEqjXTI5Y5IA6-eHInwA00QrBtD3eceH9XBrFw-pRS
10. http://www.jb51.net/article/54613.htm
11. http://zhidao.baidu.com/link?url=6tFgSgee6J90lDz5sGDDDXXFQPE3rrqoY8uCs-XEbIlBZJhCeJOKQZn0bLm762pPDV7TGbnvGosLD8P3DreqHq