检查外部类型
假定有一个拥有两个源文件的的C程序,一个个文件中包含外部变量的声明:extern int n; 另一个文件中包含外部变量n的定义:long n; 且这两个语句都不再任何一个函数体内,因此n是外部变量。
这是一个无效的C程序,因为同一个外部变量名在两个不同的文件中被声明为不同的类型。
编译器在编译一个文件时,并不知道另一个文件的内容。连接器可能对C语言一无所知,因此它也不知道如何比较两个n的定义中的类型。
一 原因
这个程序运行时,存在很多可能的情况:
1 C语言编译器足够“聪明”,能够检测到这一类型冲突。你将会得到一条诊断消息,报告变量n在两个不同的文件中被定义了不同的类型。
2 int 和long 类型在数值内部表示是一样的。尤其在32位计算机上,一般都是如此处理。程序可能正常工作,就像n在两个文件中都被声明为long 或int 类型一样。
3 变量n的两个实例虽然要求的存储空间的大小不同,但是它们共享存储空间的方式却恰好能够满足这样的条件:赋给其中一个的值,对另一也是有效的。举例:如果连接器安排int类型的n与long类型的低端部分共享存储空间,这样给每个long类型的n赋值,恰好相当于把其低端部分赋给了int类型n。本来错误的程序因为某种巧合却能够工作。
4 变量n的两个实例共享存储空间方式,使得对其中一个赋值相当于同时给另一个赋了完全不同的值。这种情况程序不能正常工作。
二 解决方法
因此保证一个特定名称的所有外部定义在每个模块中都有相同的类型是程序员的责任。“相同类型”应该是严格意义上的相同。
在一个文件中包含定义:
char filename[] = "/etc/passwd";
而在另一个文件中包含声明:
extern char *filename;
尽管在某些上下文环境中,数组和指针非常类型,但它们毕竟不同。连接仍然会报错。
修改方案1:
char filename[] = "/etc/passwd"; // file1
extern filename[]; // file2
修改方案2:
char *filename = "/etc/passwd"; // file1
extern char *filename; // file2