关于c99标准6.2.2中的第四点的理解

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,23) if the prior declaration specifies internal or
external linkage, the linkage of the identifier at the later declaration is the same as the

linkage specified at the prior declaration.If no prior declaration is visible, or if the prior
declaration specifies no linkage, then the identifier has external linkage.

对于使用extern声明的标识符,刚好在这个extern的声明之前有一个相同的声明的标识符,而且之前的标识符对于extern声明的标识符是可见的,如果之前的标识符是internal或者external linkage,那么之后的标识符与之前额标识符一样。如果在extern声明之前没有一个可见的标识符,或者之前的标识符是no linkage,那么该extern声明的标识符就是external linkage。

例子:

1、对于之前声明过相同的一个标识符,同时在这个标识符的作用域可见

static int a=0;

int main(){

extern int a;

printf("a=%d\n",a);

}

对于这种情况,则就是之前存在一个声明的标识符,而且这个标识符对于extern int a;这个作用域是可见的。

由于使用了static修饰,那么extern int a的linkage与static int a的linkage是一样的,是internal linkage。

2、对于之前声明过的相同的标识符,同时在这个标识符的作用域可见

int main(){

extern int a;  //1

extern int a; //2

printf("a=%d\n",a);

}

}

对于这种情况,在1处声明了一个标识符a,在2处是可见的,2处声明了一个相同的标识符,由于之前使用了extern修饰符,则这两个标识符都是external linkage。

3、对于之前没有出现过的声明的标识符或者在这个作用域内不可见的

int mian(){

extern int a; //2

printf("a=%d\n",a);

}

2处的a是一个external linkage的标识符。因为之前没有声明过一个相同的标识符a。

或者

int mian(){

int a=0;

{extern int a; //2

printf("a=%d\n",a);}

}

2处的标识符也是一个external linkage的标识符。因为之前虽然有一个int a=0;的声明,但是由于int a=0;这个声明是一个no linkage,所以2处是一个external的linkage。

4、对于一个全局的声明来说

例如

int a=0;  //1

int main()

{

extern int a; //2

printf("a=%d\n",a);

}

对于2处的声明,是一个external的linkage声明,虽然1处的声明,由于具有文件范围,同时没有任何修饰符,所以1处是external的linkage,那么由于1处有一个声明是external的,同时由于1处对于2处是可见的,所以2处的linkage也是external的。

我们将int a=0;换一个位置,放到后面。

int main()

{

extern int a; //2

printf("a=%d\n",a);

}

int a=0;  //1

此时,对于2来说,之前没有一个可见的标识符a,所以2就是external的linkage。同时对于1处的a来说,a具有文件范围的作用域,同时a没有static修饰符,所以,a是external的linkage,所以1和2会连接到同一个存储对象。


注意:使用external声明的标识符,并不产生了一个存储对象,所以就必须在别的地方使用正常的方式,例如int a=0;这种方式来声明一个相同的标识符,从而产生一个存储对象,否则就会产生未定义的引用的链接错误。即由于找不到一个存储对象而连接错误。

那么由上面可以得到,如果一个变量是外部链接的,那么必须存在某一个文件中声明了这样一个相同的变量,具有文件作用域,该声明必须产生一个存储对象,也就是内存存储的位置,也就是说必须采用int xxxx;这种形式。

猜你喜欢

转载自blog.csdn.net/lengye7/article/details/80233583