看下面这个例子:
image.png
为什么libc.a中已有printf定义,自己又定义了一个printf,却没有报符号重定义错误?
下面用一个小工程解释这个问题。
工程中有三个源文件,a.c、b.c、main.c。a.c和b.c生成静态库libsub.a,main.c生成应用并链接libsub.a。
头文件common.h中的内容如下:
#ifndef COMMON_H_
#define COMMON_H_
void funa1(void);
void funa2(void);
void funb(void);
#endif
源文件a.c中的内容如下:
#include "common.h"
void funa1(void)
{
}
void funa2(void)
{
}
源文件b.c中的内容如下:
#include "common.h"
void funb(void)
{
}
CMakeLists.txt中的内容如下:
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调用funb
image.png
生成的应用中只有符号funb,而没有funa1和funa2
main调用funa1
image.png
生成的应用中有符号funa1和funa2,而没有funb。
从以上两个例子中可以得到一个结论:应用链接静态库时,是以object为单位来链接的。应用用到哪个函数,就会把定义了这个函数的object中的所有函数都链接进来。没有用到的object不会链。
main实现funb,并调用funb
image.png
main实现funa1,并调用funa1
image.png
从以上两个例子中可以得到一个结论,应用只有未解析的符号才会去库里找。如果符号能解析,就不会再去库里找这个符号了。上面两个图中的funb和funa1都是main中自己定义的函数。
main实现funa1,并调用funa2
image.png
出现符号重定义错误了。因为main中没有定义funa2,要去libsub.a中找,把a.c中所有函数都链了进来,出现了两个funa1的定义。