c语言的定义与声明

声明

很多人都不太明白声明这玩意有什么用。

  • 我定义一个变量:
    1.分配了内存

2.初始化了数据
3.以后可以存取

  • 但是声明这玩意,好像什么也没干哪!

声明(declaration )指定了一个变量的标识符,用来描述变量的类型,是类型还是对象,或者函数等。声明,用于编译器(compiler)识别变量名所引用的实体。以下这些就是声明:

  • extern int bar;

  • extern int g(int, int);

  • double f(int, double); // 对于函数声明,extern关键字是可以省略的。

  • class foo; // 类的声明,前面是不能加class的。

要理解声明,就得了解连接器(linker).我们知道c语言是分开编译。

gcc -c 1.c 2.c 3.c

c编译器会输出1.o 2.o 3.o

注意
编译器根本不知道3者之间的关系:

  • 1.c中是否调用了2.c中定义的函数f()

  • 2.c是否修改了3.c中定义的变量var

注意编译器压根不知道这么复杂的邻里关系,七舅姥爷的远亲表姨。

举个例子:

1.c


int main(){
    f();
    return 0;
}

gcc -c 1.c

报错defined refernece to f

但是你加上

extern void f();

int main(){
    f();
    return 0;
}

就OK了,编译就通过!
声明就是告诉编译器,我这个是使用别人的,你别报错!到时候连接器会帮我找到的。

gcc 1.c 2.c 3.c

连接器负责在其他两个模块里找f的定义

定义

定义是对声明的实现或者实例化。
连接器(linker)需要它(定义)来引用内存实体。
与上面的声明相应的定义如下:

  • int bar;

  • int g(int lhs, int rhs) {return lhs*rhs;}

  • double f(int i, double d) {return i+d;}

  • class foo {};// foo 这里已经拥有自己的内存了,对照上面两个函数,你就应该明白{}的用处了吧?

注意
定义只能使用一次!
如果你定义变量超过一次,连接器是不知道把reference和哪块内存连接,然后就会报 duplicated symbols这样的错误了(symbols是指定义后的变量名)。

总结

总之,最终原因是c采用分开编译,最终连接的方式。
所以声明就成为linker去寻找其定义的钥匙。它只是为了给编译器提供引用标识,让编译器能够知道有这个引用,能用这个引用来引用某个实体。

声明是为了让编译器正确处理对声明变量和函数的引用。
定义是一个给变量分配内存的过程,或者是说明一个函数具体干什么用。

本文固定链接: http://www.js-code.com/c/c_61831.html