C语言定义和声明区别

1. 变量的定义和声明

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

2. 强符号和弱符号

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

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

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

3. 实例

实例1:多个强符号

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

test11.h:

#ifndef _TEST1_H
#define _TEST1_H
#include <stdio.h>
int i=1; //此处i是定义,是强符号
void printmsg();
#endif

test11.c

#include "test11.h"
void printmsg(){
  printf("i=%d\n",i);
}

test22.c

#include "test11.h"
int main(){
 printmsg();
 return 0;
}

编译结果:

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

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


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

test11.h

#ifndef _TEST1_H
#define _TEST1_H
#include <stdio.h>
int i;
int i;
void printmsg();
#endif
此处int i,准确来说是定义性声明,既是定义也是声明,但没有初始化,称为弱符号。


test11.c

#include "test11.h"
void printmsg(){
  printf("i=%d\n",i);
}

test22.c

#include "test11.h"
int i=10;
int main(){
 printmsg();
 return 0;
}

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

运行结果:

i=10

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


实例3:多个弱符号

test11.h

#ifndef _TEST1_H
#define _TEST1_H
#include <stdio.h>
int i;
int i;
void printmsg();
#endif
此处int i,准确来说是定义性声明,既是定义也是声明,但没有初始化,称为弱符号。


test11.c

#include "test11.h"
void printmsg(){
  printf("i=%d\n",i);
}

test22.c
#include "test11.h"
 int main(){
 printmsg();
 return 0;
}

去掉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)需要强调的是,不要在头文件定义全局变量,容易引起重定义。

猜你喜欢

转载自blog.csdn.net/chenjin_zhong/article/details/12026591