CodeBlocks编译多文件C项目提示undefined reference错误求助
CodeBlocks编译C项目报undefined reference错误排查
报错信息
E:\CodeBlocks\Projects\Triplet-CLEON-Benjamin\main.c|5|undefined reference to `initTriplet'| C:\msys64\mingw64\bin\..\lib\gcc\x86_64-w64-mingw32\12.1.0\..\..\..\..\x86_64-w64-mingw32\bin\ld.exe: E:\CodeBlocks\Projects\Triplet-CLEON-Benjamin\main.c|7|undefined reference to `AfficheTriplet'|
异常表现
- 项目共包含3个文件,目录结构符合常规规范:
- ProjectName
- Sources
- main.c
- triplet.c
- Headers
- triplet.h
- Sources
- ProjectName
- 各文件代码逻辑无语法错误,内容如下:
main.c
triplet.c#include "triplet.h" int main() { triplet myTriplet = initTriplet(5,8,7); AfficheTriplet(myTriplet); return 0; }
triplet.h#include "triplet.h" #include <stdio.h> void AfficheTriplet(triplet myTriplet) { printf("Triplet: \n\t Premier %d\n\t Second %d\n\t Troisieme %d", myTriplet.p, myTriplet.d, myTriplet.t); } triplet initTriplet(int a, int b, int c) { triplet myTriplet = {a,b,c}; return myTriplet; }#ifndef TRIPLET_H_INCLUDED #define TRIPLET_H_INCLUDED typedef struct triplet triplet; struct triplet { int p; int d; int t; }; triplet triTripletV1(triplet myTriplet); void triTripletV2(triplet myTriplet); void AfficheTriplet(triplet myTriplet); triplet initTriplet(int a, int b, int c); #endif // TRIPLET_H_INCLUDED - 异常规律:如果在
main.c中写#include "triplet.c",项目可正常编译运行;如果按规范仅引入triplet.h,就会触发上述undefined reference报错。
问题根因
这是C项目开发中非常典型的源文件未加入构建链路导致的链接阶段错误:
- C语言的头文件(.h后缀)仅用来存放结构体定义、函数声明、宏定义等前置声明内容,作用是给编译器做语法检查时提供类型参考,本身不会被单独编译,也不包含函数的实际可执行代码;函数的具体实现全部存放在.c后缀的源文件中。
- 当前CodeBlocks项目配置存在问题:
triplet.c没有被纳入项目的编译、链接目标列表,构建项目时编译器只会处理main.c这一个源文件。到链接阶段,链接器找不到initTriplet、AfficheTriplet两个函数对应的实际实现地址,就会抛出未定义引用报错。 - 写
#include "triplet.c"能正常运行的本质是:#include是纯文本预处理指令,写这句话相当于在预处理阶段把triplet.c的全部内容直接插入到main.c的对应位置,两个文件的代码被合并为同一个编译单元,所有函数实现都在同一个文件里,链接器自然能找到符号。但这是完全不符合C项目开发规范的错误写法,项目规模变大后会直接引发重复定义、编译效率极低等一系列问题,绝对不要在实际开发中这么用。
解决方法
按以下步骤调整CodeBlocks项目配置即可修复问题:
- 打开出问题的项目,在左侧管理面板的「Projects」视图下,展开Sources目录,检查列表中是否存在
triplet.c - 如果Sources目录下看不到
triplet.c,右键项目根节点,选择Add files...选项,在弹出的文件选择窗口中找到项目路径下存放的triplet.c,确认添加到项目 - 添加文件时会弹出构建目标选择窗口,把日常使用的Debug、Release两个构建目标全部勾选,确保该文件会被两个构建配置识别处理
- 右键已经添加到项目中的
triplet.c,选择Properties选项,切换到Build标签页,确认Compile file和Link file两个复选框都处于勾选状态 - 打开
main.c,删除其中如果存在的#include "triplet.c"语句,仅保留规范的#include "triplet.h"引入 - 点击顶部菜单栏的
Build -> Clean选项,清理之前生成的错误构建缓存,再重新点击Build按钮构建项目,报错就会完全消失。
内容的提问来源于stack exchange,提问作者Benji HS
相关产品推荐
相关产品推荐

