在一个里定义了一个:char a[6];
在另外一个文件里用下列语句进行了声明:extern char *a;
请问,这样可以吗?
答案与分析:
1)、
不可以,程序运行时会告诉你非法访问。原因在于,指向类型T的并不等价于类型T的数组。extern char *a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]。
2)、例子分析如下,如果a[] = "abcd",则外部变量a=0x12345678 (数组的起始地址),而*a是重新定义了一个a的地址可能是0x87654321,直接使用*a是错误的.
3)、这提示我们,在使用extern时候要
严格对应声明时的格式,在实际编程中,这样的错误屡见不鲜。
4)、extern用在声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在*.h中并用extern来声明。
这个真的比较可恶,在声明()的时候,这个extern居然可以被省略,所以会让你搞不清楚到底是
声明还是
定义,下面分变量和函数两类来说:
尤其是对于变量来说。
extern int a;//
声明一个全局变量a
int a; //
定义一个全局变量a
extern int a =0 ;//
声明一个全局变量a 并给初值,这个变量是在其他文件中定义的,编译器会在其他文件寻找给它分配的内存,并给它赋值。
int a =0;//
定义一个全局变量a,并给初值,
声明之后你不能直接使用这个变量,需要定义之后才能使用。
第四个等于第三个,都是定义一个可以被外部使用的全局变量,并给初值。
糊涂了吧,他们看上去可真像。但是
定义只能出现在一处。也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个
extern int a可以出现很多次。
当你要
引用一个全局变量的时候,你就要
声明extern int a;这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。
附:从编译原理上来说,声明是仅仅告诉编译器,有个某类型的变量会被使用,但是编译器并不会为它分配任何内存。而定义就是分配了内存。
对于下面的两句代码:
void Func()
{
int a;
int b=1;
a=0;
}
对于第一行代码,编译器不会做任何事,它不会为它在栈中分配一点东西,直到第三句,a=0;时,编译器才会将其压入栈中。而对于int b=0;这一句,编译器就会生成一条指令,为它赋值。如果反汇编,看到的代码可能是这样的:
push 1;
push 0;
当然,并不一定编译器就会样做,也有可能在声明int a时,编译器就会把一个废值入栈,到第三条再为其赋值,这要看编译器的具体取舍,所以,声明不一定不是定义,而定义一定是定义。
但是,下面的声明,一定仅仅是声明:
extern int a;
这表时,有一个int变量a,它一定是在另外其他地方定义的,所以编译器此时一定不会做什么分配内存的事,因为它就是声明,仅仅表明下面的代码引用了一个符号,而这个符号是int类型的a而已。
阅读(2424) | 评论(0) | 转发(0) |