Почему глобальные переменные в файле заголовка вызывают ошибку ссылки?

Я всегда получаю следующую ошибку, даже если я поставил 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 }; 

    определить те глобальные переменные независимо от того, находятся ли эти коды в файле заголовка или непосредственно в .c ( #include – это просто текстовая вставка содержимого заголовка). Вместо этого вы должны иметь определения в exaccty один исходный файл и изменить заголовок, чтобы вместо этого предоставить выражение extern :

     extern const char *Bittorrent; extern const char *eight_byte; 

    Затем все ваши источники, использующие переменные, могут быть скомпилированы, но компоновщик будет только переменными.

    Потому что вы определяете переменные в файле заголовка. Тогда все исходные файлы, содержащие заголовочный файл, будут иметь указанные переменные.

    Вы можете объявить переменные, используя ключевое слово 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; 

    Главная (до основной функции / как глобальная переменная):

     const char *Bittorrent = "BitTorrent protocol"; 

    Таким образом, ваш заголовок сообщает каждому файлу, что есть переменная с именем «Bittorrent», но только ваш файл main.c имеет часть, в которой он действительно создан.

    Путем инициализации переменной вы определяете ее в каждом месте, в которое включен файл. Предполагая, что эти модули связаны друг с другом, теперь у вас есть несколько определений, что является ошибкой.

    Вы можете объявить переменную в своем заголовке с тегом extern и затем инициализировать ее в одном из ваших .c-модhive.

    В вашем файле .h:

     extern int i; 

    В одном из ваших .c файлов:

     int i = 1; 

    Тем не мение,

    Также обратите внимание, что у вас есть опечатка.

    Send_fisrt_Handshake вместо Send_first_Handshake .

    Я могу представить, что вы просто заманили его в свой вопрос. Но вы никогда не знаете; опечатки могут быть трудно найти и исправить в большом коде. 🙂