C语言定义和声明区别

来源:互联网 发布:简单有趣的vb小程序 编辑:程序博客网 时间:2024/06/01 07:51

C语言定义和声明区别

1. 变量的定义和声明

C语言定义和声明分为变量的定义和声明和函数的定义和声明。由于,函数是具有全局外部特性,并且函数的定义和声明区别是很明显的。其声明需要返回值类型,函数名和参数列表。而函数的定义需要函数体。所以,很容易区别函数的声明和定义。对于变量的声明和定义,就不是那么明显。通常变量定义和声明的区别是有没有为变量分配内存。如果为变量分配内存就是定义,否则就是声明。变量声明可以出现多次,但定义只能出现一次。

2. 强符号和弱符号

强符号:函数和初始化的全局变量称为强符号。

弱符号:  未初始化的全局变量称为弱符号。

在程序中,强符号只能出现1次,弱符号会出现多次。如果存在一个强符号和多个弱符号,gcc会选择强符号。如果存在多个弱符号,会选择其中一个弱符号作为定义,并分配内存。

3. 实例

实例1:多个强符号

三个文件test11.h, test11.c和test22.c,具体如下:

test11.h:

[cpp] view plaincopy
  1. #ifndef _TEST1_H  
  2. #define _TEST1_H  
  3. #include <stdio.h>  
  4. int i=1; //此处i是定义,是强符号  
  5. void printmsg();  
  6. #endif  

test11.c

[cpp] view plaincopy
  1. #include "test11.h"  
  2. void printmsg(){  
  3.   printf("i=%d\n",i);  
  4. }  

test22.c 

[cpp] view plaincopy
  1. #include "test11.h"  
  2. int main(){  
  3.  printmsg();  
  4.  return 0;  
  5. }  

编译结果:

test11.o:(.data+0x0): multiple definition of `i'
test22.o:(.data+0x0): first defined here

由于出现了多个强符号,所以链接时i重定义了。


实例2:多个弱符号和1个强符号

test11.h

[cpp] view plaincopy
  1. #ifndef _TEST1_H  
  2. #define _TEST1_H  
  3. #include <stdio.h>  
  4. int i;  
  5. int i;  
  6. void printmsg();  
  7. #endif  
此处int i,准确来说是定义性声明,既是定义也是声明,但没有初始化,称为弱符号。


test11.c

[cpp] view plaincopy
  1. #include "test11.h"  
  2. void printmsg(){  
  3.   printf("i=%d\n",i);  
  4. }  

test22.c

[cpp] view plaincopy
  1. #include "test11.h"  
  2. int i=10;  
  3. int main(){  
  4.  printmsg();  
  5.  return 0;  
  6. }  

在test33.c对i进行了定义,为强符号。

运行结果:

i=10

当存在多个弱符号和1个强符号时,gcc会选择强符号,能够正常的编译和运行。


实例3:多个弱符号

test11.h

[cpp] view plaincopy
  1. #ifndef _TEST1_H  
  2. #define _TEST1_H  
  3. #include <stdio.h>  
  4. int i;  
  5. int i;  
  6. void printmsg();  
  7. #endif  
此处int i,准确来说是定义性声明,既是定义也是声明,但没有初始化,称为弱符号。


test11.c

[cpp] view plaincopy
  1. #include "test11.h"  
  2. void printmsg(){  
  3.   printf("i=%d\n",i);  
  4. }  

test22.c
[cpp] view plaincopy
  1. #include "test11.h"  
  2.  int main(){  
  3.  printmsg();  
  4.  return 0;  
  5. }  

去掉test22.c中的i定义,此时只有多个弱符号。

运行结果:

i=0;

当存在多个弱符号时,gcc会选择其中一个弱符号作为定义。由于i未初始化,所以存储在.bss段上,关于变量存储位置,将在以后文章作详细介绍。.bss段变量用0进行填充。

注意: 当GCC编译器看到 int i时,在链接的时候,搜索源程序,如果定义变量i(有初始值),就把此处的i看成是声明。如果别处没有定义,就为此处的i分配空间,即当作定义。

所以: i的转换过程为:定义性声明((或称为暂定义)->定义。


4. 结构体的定义和声明

struct A{

  int i;

 int j;

};

称为类型定义,和变量定义完全不同。即定义一种新的数据类型,类似int类型。如果GCC在编译时检查出多个结构体定义,就会报重定义错误。即某个程序出现了:

struct A{};

struct A{};

在链接时,如果多个文件中存在结构体定义,则不会报错,gcc在链接时只检查符号,这里的符号指的是变量和函数之类的符号,而不是类型符号。不会检查语法。所以在多个文件中出现结构体定义没有问题。

struct A A1;

A1称为结构体变量声明,和普通变量类似。

总结:

(1)变量定义和声明的本质区别:是否分配内存。

(2)局部变量不能多次声明,即在同一代码块(即同一作用域)的局部变量不可多次声明。局部变量不能出现 int i; int i;

(3)需要强调的是,不要在头文件定义全局变量,容易引起重定义。

0 0
原创粉丝点击