C语言中符号解析规则如下:
1.不允许有多个符号的定义,这里的符号指的是变量或者函数。
2.如果有一个符号定义和多个符号的声明,则选择被定义的符号。
3.如果有多个符号的声明,则从其中任选一个作为符号的定义。
声明和定义有什么区别:
声明,表示告知编译器,该变量的存在,此时是不为该变量分配存储空间的。
定义,不仅告知编译器该变量存在,而且为该变量赋值。由于需要赋值,所以该变量的存储空间就被分配了。
当该变量的作用域范围内只有声明,而没有该变量的定义时,编译器会自动的将第一个声明认为是变量的定义。
void f(){
int b; /*在这里声明变量b,由于在该函数中,没有找到对变量b的定义。
因此该声明被认为是变量的定义,这时分配了4个字节存储空间给b
*/
b = 2; //这里是对变量进行赋值,不是定义。
}
下面这个问题,我总结为链接规则所引发的全局变量值被覆盖的情形:
a.c 函数如下:
//下面是a.c文件中的代码
#include
void f(void);
//全局变量的定义
int a = 123;
int b = 121;
int main(void)
{
f();
printf("a = %d,b = %d\n",a,b);
return 0;
}
//下面是b.c中的代码
double a;
void f()
{
a = 0.0;
}
两个源文件中都有对全局变量a的定义和全局变量a的声明,根据如上规则2,所以不会造成链接错误。编译器会选择符号的定义。这是f()函数执行的时候,里面调用的 a 其实是在a.c中定义的全局变量。所不同的是由于b.c中声明的变量类型为双精度型,所以对该变量进行赋值为0.0的时候,需要将由 a 所指的内存空间的首地址开始的8个字节清 0 ,而不是4个字节。因此变量 a 后面的变量b的存储空间就被覆盖掉了。因此,最后输出的结果是:a = 0, b = 0