一。、首先要知道强弱符号
编译器编译源文件时会把源文件的全局符号(global symbol)分成强(strong)和弱(weak)两类传给汇编器,
而随后汇编器则将强弱信息编码并保存在目标文件的符号表中。
那么何谓强弱呢?编译器认为函数与初始化了的全局变量都是强符号,而未初始化的全局变量则成了弱符号。
比如有这么个源文件:
extern int errorno;
int buf[2] = {1,2};
int *p;
int main()
{
return 0;
}
其中main、buf是强符号,p是弱符号,而errorno则非强非弱,因为它只是个外部变量的使用声明。
有了强弱符号的概念,我们就可以看看链接器是如何处理与选择被多次定义过的全局符号:
规则1: 不允许强符号被多次定义(即不同的目标文件中不能有同名的强符号);
规则2: 如果一个符号在某个目标文件中是强符号,在其它文件中都是弱符号,那么选择强符号;
规则3: 如果一个符号在所有目标文件中都是弱符号,那么选择其中任意一个;
二、然后来看这个问题
C/C++code
/* headerer.h */
#ifndef HEADER_H_
#define HEADER_H_
#include <stdio.h>
const int X = 10;
void func1(void);
void func2(void);
#endif
C/C++ code
/* file1.c */
#include "headerer.h"
void func1(void)
{
printf("This is file1. X =%d\n", X);
return;
}
C/C++ code
/* file2.c */
#include "headerer.h"
void func2(void)
{
printf("This is file2. X =%d\n", X);
return;
}
C/C++ code
/* main.c */
#include "headerer.h"
int main()
{
printf("This is main. X =%d\n", X);
func1();
func2();
return 0;
}
在VC6.0中,由上述4个文件(headerer.h, file1.c, file2.c, main.c)组成的工程为什么编译报错?
但如果将file1.c, file2.c, main.c三个文件名改为file1.cpp, file2.cpp, main.cpp,其他不变的情况下却可以正确运行。
为什么啊?难道C和C++差异很大吗?记得在C++中,用const声明的变量具有内部连接性,因此上述改为.cpp的工程可以正月编译并执行。C语言中难道不是这样吗?
答案:C++中const默认为定义他的文件的局部变量,而C中认为是extern的量。但是在c中若constint X = 10; 把“=10”去掉。 那也可以编译成功了,因为这些定义都是弱符号,C语言可以支持多个弱符号。