为何包含含结构体定义的头文件不会触发重定义错误?
为何包含含结构体定义的头文件不会触发重定义错误?
这问题其实涉及到C语言编译流程里的「编译单元」概念,我给你一步步掰扯清楚:
首先得明确C代码的编译逻辑:每个.c源文件都是一个独立的编译单元。编译器会分开处理每个编译单元:先通过预处理器把#include的内容直接“粘贴”到当前文件里,接着把这个展开后的文件编译成目标文件(比如.o格式),最后才是把所有目标文件链接成最终的可执行程序。
回到你的代码场景:
structs.h里的结构体定义,会被分别展开到structs.c和main.c这两个独立的编译单元中。编译器处理structs.c时,只会看这个文件展开后的内容(里面只有一份结构体定义);处理main.c时也是同理。因为两个编译单元是完全独立处理的,各自内部都只有一份结构体定义,自然不会触发重定义错误。- 到了链接阶段,链接器只关心函数、全局变量这些可寻址的符号,结构体是编译器在编译阶段用来做类型检查的“本地信息”,链接器根本不会去管结构体的定义——只要各个编译单元里的结构体定义完全一致,就不会有问题(如果不一致会导致未定义行为,但不会直接报重定义错误)。
那为什么你手动在main.c里再加一遍结构体定义就会报错呢?
当你在main.c里手动写了一遍typedef struct point{...} Point;后,预处理器先把structs.h的内容展开,这时候main.c里已经有了一份结构体定义,紧接着你又写了一模一样的定义——这就变成同一个编译单元里出现了两次完全相同的结构体类型定义,这直接违反了C语言的规则(同一个作用域内不能重复定义同一结构体类型),所以编译器立刻就会抛出重定义错误。
另外补充个小知识点:如果你的头文件没加头文件保护(比如#ifndef STRUCTS_H #define STRUCTS_H ... #endif或者#pragma once),要是某个.c文件不小心多次包含同一个头文件,那也会在同一个编译单元里出现重复定义,这时候同样会报错。你的例子里每个.c只包含了一次头文件,所以没触发这个问题。
内容来源于stack exchange
相关产品推荐
相关产品推荐

