链接属性再总结
1.extern int a = 1;和extern int a;的区别
代码块之外
extern int a = 1;
int a = 1;
上述代码没有任何区别,代码快之外,在缺省关键字extern情况下,变量a的默认链接属性就是external,extern int a = 3;表示在显式地声明这个变量的链接属性时external
上面的代码会在静态内存中分配空间
extern int a;
int a; //如果其他文件定义并初始化,缺省extern和加上extern等价
//当然,如果其他文件没有定义,这里表示定义,默认初始化值为0
这句话仅仅是声明,并不会分配内存空间,这句话告诉编译器,这个变量a在另一个文件中,编译后,链接时,到其他文件中寻找变量a(外部链接属性)
2.报错分析
A.将全局变量的定义错误的放到头文件中
main.o main.c:(.data+0x0): multiple definition of `a'
test.o test.c:(.data+0x0): first defined here
源文件1:
/*main.c*/
#include <stdio.h>
#include "test.h"
int main(void){
printf("%d",a);
return 0;
}
源文件2:
/*test.c*/
#include "test.h"
void test(){
a++;
}
头文件:
#ifndef TEST_H
#define TEST_H
int a = 3;
#endif
可能这个例子很蠢,但是,就是想说不要把全局变量的定义放到头文件中,这里只是一个头文件,而且还没有多重包含,如果头文件很多,而且多重包含,那错误会很难找。
分析:
问:头文件的编辑格式采用了条件编译,为什么会报错多次定义了a?
答:的每个文件都是单独编译,所以对于main.o和test.o两个文件,都有自己的变量;报错发生在链接阶段,因为缺省情况下,全局变量的定义默认为外部链接属性(多个文件使用一个实体),然而,却有两个实体,所以报错了。
总结——不要将全局变量定义放到头文件中(非要放,加上static)
全局变量加上static表示将链接属性变成内部链接属性,这样,每一个文件中的变量,在自己的文件中表示一个实体。
B.没有实体——没有定义
undefined reference to `a'
分析:
这条报错的唯一原因就是没有定义,要么就是变量名写错了,或者就是只有声明,没有定义。
/*main.c*/
#include <stdio.h>
extern int a;
int main(void){
printf("%d",a);
return 0;
}
extern int a;只是声明,告诉编译器这个变量在别的文件,但是,链接的时候,并没有找到这个变量。
C.可以多次声明,但不能多次定义
最简单的例子:函数原型,多次声明同一个函数原型并不会报错。
int f();
int f();
这样并不会报错。
同样
extern int a;
extern int a;
也不会报错。
在说明一下:
extern int f();
int f();
这两个原型等价,链接属性都是external,一个显式表示,一个隐式表示。