静态库本质是ELF格式重定位目标文件(.o)的归档,非源码打包;必须用gcc -c生成.o,再用ar归档,否则链接失败。

静态库本质是目标文件的归档,不是源码打包
因为 ar 只能打包已编译的目标文件(.o),不能直接处理 .c 源文件。静态库不是“把源码压缩一下”,而是把链接器能识别的、已翻译好的机器指令片段(即重定位目标文件)集合起来。源码必须先经过预处理、编译、汇编三步,生成符合 ELF 格式的 .o,才能被 ar 归档。
gcc -c 是唯一可靠生成可链接目标文件的方式
直接运行 gcc add.c sub.c -o libmath.a 不会生成静态库,反而会尝试链接出可执行文件,报错 undefined reference to 'main'。正确做法是加 -c 参数:
-
gcc -c add.c→ 输出add.o(无main符号,只含add函数定义) -
gcc -c sub.c→ 输出sub.o -
ar rcs libmath.a add.o sub.o→ 把两个合法目标文件打包
漏掉 -c 或误用 -o 指向 .a 文件名,GCC 会按默认行为走完整编译流程,必然失败。
目标文件里藏着符号表和重定位信息,静态库靠它工作
每个 .o 文件包含:.text(代码)、.data(初始化数据)、.symtab(符号表)、.rela.text(重定位入口)。链接器在最终链接时,正是靠这些信息从 libmath.a 中提取需要的函数,并修正地址引用。如果跳过目标文件阶段,这些结构根本不存在——ar 打包的只是二进制垃圾,链接时会报 undefined reference,哪怕函数名拼写完全正确。
常见错误:用 ar 直接打包 .c 文件或目录
比如:ar rcs libmy.a *.c 或 ar rcs libmy.a src/,结果生成的 .a 文件看似存在,但里面全是源码文本或目录结构,链接时完全不可用。验证方法很简单:ar -t libmy.a 应该列出 xxx.o,而不是 xxx.c;file add.o 应显示 “ELF 64-bit LSB relocatable”,而非 “C source”。
真正容易被忽略的是:目标文件不是中间产物,而是静态库的唯一合法构件。哪怕只改一行代码,也得重新 gcc -c 生成新 .o,再 ar r 替换归档里的对应成员——不能只替换源码再重打包。


















