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