什么也不做。它会作为函数地址被求值,但不会调用它596。
9悬挂 问题
一个 总是与其最近的 . 相关联。
连接
一个 程序可能有很多部分组成,它们被分别编译,并由一个通常称为连接器、连接编辑器或加载器的程
序绑定到一起。由于编译器一次通常只能看到一个文件,因此它无法检测到需要程序的多个源文件的内容
才能发现的错误。
你必须自己检查外部类型
假设你有一个 程序,被划分为两个文件。其中一个包含如下声明:
)
而令一个包含如下声明:
)
这不是一个有效的 程序,因为一些外部名称在两个文件中被声明为不同的类型。然而,很多实现检测不
到这个错误,因为编译器在编译其中一个文件时并不知道另一个文件的内容。因此,检查类型的工作只能
由连接器(或一些工具程序如 )来完成;如果操作系统的连接器不能识别数据类型, 编译器也没法
过多地强制它。
那么,这个程序运行时实际会发生什么?这有很多可能性:
实现足够聪明,能够检测到类型冲突。则我们会得到一个诊断消息,说明 在两个文件中具有不同的
类型。
你所使用的实现将 和 视为相同的类型。典型的情况是机器可以自然地进行 位运算。在这
种情况下你的程序或许能够工作,好象你两次都将变量声明为 (或 )。但这种程序的工作纯属偶
然。
的两个实例需要不同的存储,它们以某种方式共享存储区,即对其中一个的赋值对另一个也有效。
这可能发生,例如,编译器可以将 安排在 的低位。不论这是基于系统的还是基于机器的,这种程
序的运行同样是偶然。
的两个实例以另一种方式共享存储区,即对其中一个赋值的效果是对另一个赋以不同的值。在这种
情况下,程序可能失败。
这种情况发生的另一个例子出奇地频繁。程序的某一个文件包含下面的声明:
(:;56#2+#)
而另一个文件包含这样的声明:
(:;)
尽管在某些环境中数组和指针的行为非常相似,但它们是不同的。在第一个声明中,:; 是一个
字符数组的名字。尽管使用数组的名字可以产生数组第一个元素的指针,但这个指针只有在需要的时候才
产生并且不会持续。在第二个声明中,:; 是一个指针的名字。这个指针可以指向程序员让它指向
的任何地方。如果程序员没有给它赋一个值,它将具有一个默认的 , 值(<=>>)(5译注6实际上,在
中一个为初始化的指针通常具有一个随机的值,这是很危险的!)。
这两个声明以不同的方式使用存储区,它们不可能共存。