为什么头文件中的全局变量会导致链接错误?

我总是得到以下错误,即使我已将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

我可以想象你只是把它输错到你的问题中。 但你永远不知道; 在大型代码中很难找到并修复拼写错误。 🙂