C语言中声明与定义

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.csdn.net/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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值