为什么头文件中的全局变量会导致链接错误?
我总是得到以下错误,即使我已将include guard放入头文件中。
duplicate symbol _Bittorrent in: /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/main.o /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/Handshake.o duplicate symbol _eight_byte in: /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/main.o /Users/tracking/Library/Developer/Xcode/DerivedData/SHT-giuwkwyqonghabcqbvbwpucmavvg/Build/Intermediates/SHT.build/Debug/SHT.build/Objects-normal/x86_64/Handshake.o ld: 2 duplicate symbols for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
这是.h头文件,.c文件和main.c
main.c中
#include "Handshake.h" int main(int argc, char** argv) { // some code. return 0; }
Handshake.h
#ifndef SHT_Handshake_h #define SHT_Handshake_h const char *Bittorrent = "BitTorrent protocol"; const char eight_byte[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif
Handshake.c
#include "Handshake.h" int Send_fisrt_Handshake(download_connection *pPeer, Handshake *necessary_info) { //some statements return 1; } void Set_Handshake_information(TorrentFile* pArg, Handshake *pYours) { //some statements }
但是,如果我从头文件中删除了全局变量,这些代码将成功编译。
我不明白为什么。 有人可以解释原因吗? 先感谢您。
线条像
const char *Bittorrent = "BitTorrent protocol"; const char eight_byte[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
定义全局变量,无论代码是在头文件中还是在a .c中直接( #include
只是文本插入标题的内容)。 相反,您应该在exaclty一个源文件中定义并更改标头以提供extern
声明:
extern const char *Bittorrent; extern const char *eight_byte;
然后可以编译使用thes变量的所有源代码,但链接器只会变量一次。
因为您在头文件中定义变量。 然后,包含头文件的所有源文件都将定义这些变量。
您可以使用extern
关键字声明变量:
extern const char *Bittorrent; extern const char eight_byte[8];
然后在一个源文件中定义变量。
或者您可以将变量定义为static
,这会将其范围限制为转换单元(即源文件):
static const char *Bittorrent = "BitTorrent protocol"; static const char eight_byte[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
这与C ++不同,其中const
也表示static
。
标题:
extern const char *Bittorrent;
Main(在main函数之前/作为gloabal变量):
const char *Bittorrent = "BitTorrent protocol";
这样你的标题就会告诉每个文件有一个名为“Bittorrent”的变量,但是只有你的main.c文件中有一个真正创建它的部分。
通过初始化变量,您可以在包含文件的每个位置定义它。 假设这些模块链接在一起,您现在有多个定义,这是一个错误。
您可以使用extern标记在标头中声明变量,然后在其中一个.c模块中初始化它。
在你的.h文件中:
extern int i;
在你的一个.c文件中:
int i = 1;
然而,
还要注意你有一个错字。
Send_fisrt_Handshake
而不是Send_first_Handshake
。
我可以想象你只是把它输错到你的问题中。 但你永远不知道; 在大型代码中很难找到并修复拼写错误。 🙂