看下面這個(gè)例子:
為什么libc.a中已有printf定義隐轩,自己又定義了一個(gè)printf职车,卻沒有報(bào)符號(hào)重定義錯(cuò)誤鹊杖?
下面用一個(gè)小工程解釋這個(gè)問題骂蓖。
工程中有三個(gè)源文件登下,a.c被芳、b.c畔濒、main.c篓冲。a.c和b.c生成靜態(tài)庫libsub.a壹将,main.c生成應(yīng)用并鏈接libsub.a。
頭文件common.h中的內(nèi)容如下:
#ifndef COMMON_H_
#define COMMON_H_
void funa1(void);
void funa2(void);
void funb(void);
#endif
源文件a.c中的內(nèi)容如下:
#include "common.h"
void funa1(void)
{
}
void funa2(void)
{
}
源文件b.c中的內(nèi)容如下:
#include "common.h"
void funb(void)
{
}
CMakeLists.txt中的內(nèi)容如下:
cmake_minimum_required(VERSION 3.15)
project(main C CXX)
add_library(sub STATIC a.c b.c)
add_executable(main main.c)
target_link_libraries(main sub)
main調(diào)用funb
生成的應(yīng)用中只有符號(hào)funb暴区,而沒有funa1和funa2
main調(diào)用funa1
生成的應(yīng)用中有符號(hào)funa1和funa2仙粱,而沒有funb伐割。
從以上兩個(gè)例子中可以得到一個(gè)結(jié)論:應(yīng)用鏈接靜態(tài)庫時(shí),是以object為單位來鏈接的尚胞。應(yīng)用用到哪個(gè)函數(shù)笼裳,就會(huì)把定義了這個(gè)函數(shù)的object中的所有函數(shù)都鏈接進(jìn)來侍咱。沒有用到的object不會(huì)鏈密幔。
main實(shí)現(xiàn)funb胯甩,并調(diào)用funb
main實(shí)現(xiàn)funa1木柬,并調(diào)用funa1
從以上兩個(gè)例子中可以得到一個(gè)結(jié)論眉枕,應(yīng)用只有未解析的符號(hào)才會(huì)去庫里找。如果符號(hào)能解析姥宝,就不會(huì)再去庫里找這個(gè)符號(hào)了恐疲。上面兩個(gè)圖中的funb和funa1都是main中自己定義的函數(shù)培己。
main實(shí)現(xiàn)funa1省咨,并調(diào)用funa2
出現(xiàn)符號(hào)重定義錯(cuò)誤了愕乎。因?yàn)閙ain中沒有定義funa2感论,要去libsub.a中找紊册,把a(bǔ).c中所有函數(shù)都鏈了進(jìn)來囊陡,出現(xiàn)了兩個(gè)funa1的定義撞反。