Ошибки "множественного определения", "впервые определены здесь"

У меня есть 3 проекта: сервер, клиент и сообщество. Создание папок заголовка и источника в Commons не вызывает никаких проблем, и я могу свободно обращаться к функциям от сервера и клиента.

Однако по некоторым причинам создание дополнительных файлов источника/заголовка в проекте Server или Client всегда вызывает ошибки multiple definition of (...) и first defined here.

Пример:

commands.h (в корневом каталоге проекта Client)

#ifndef COMMANDS_H_
#define COMMANDS_H_

#include "commands.c"

void f123();

#endif /* COMMANDS_H_ */

commands.c (в корневом каталоге проекта Client)

void f123(){

}

main.c (в корневом каталоге проекта Client)

#include "commands.h"
int main(int argc, char** argv){

}

Ошибки:

make: *** [Client] Error 1      Client
first defined here              Client
multiple definition of `f123'   commands.c

Очистка, восстановление индекса, восстановление проектов не помогают. Не перезагружает компьютер.

Ответ 1

Проблема здесь в том, что вы включаете commands.c в commands.h перед прототипом функции. Следовательно, препроцессор C вставляет содержимое commands.c в commands.h перед прототипом функции. commands.c содержит определение функции. В результате определение функции заканчивается раньше, чем объявление функции, вызывающее ошибку.

Содержимое commands.h после фазы препроцессора выглядит так:

#ifndef COMMANDS_H_
#define COMMANDS_H_

// function definition
void f123(){

}

// function declaration
void f123();

#endif /* COMMANDS_H_ */

Это ошибка, потому что вы не можете объявить функцию после ее определения в C. Если вы поменяли местами #include "commands.c" и объявление функции, ошибка не должна произойти, потому что теперь прототип функции предшествует объявлению функции,

Тем не менее, включение файла .c является плохой практикой и его следует избегать. Лучшим решением для этой проблемы было бы включить commands.h в commands.c и связать скомпилированную версию команды с основным файлом. Например:

commands.h

#ifndef COMMANDS_H_
#define COMMANDS_H_

void f123(); // function declaration

#endif

commands.c

#include "commands.h"

void f123(){} // function definition

Ответ 2

Вы не должны включать command.c в свой файл заголовка. В общем, вы не должны включать файлы .c. Скорее, command.c должен включать команды .h. Как определено здесь, препроцессор C вставляет содержимое команд .c в команды .h, где включено. Вы получаете два определения f123 в командах .h.

commands.h

#ifndef COMMANDS_H_
#define COMMANDS_H_

void f123();

#endif

commands.c

#include "commands.h"

void f123()
{
    /* code */
}

Ответ 3

Возможно, вы включили файл .c в make файл несколько раз.

Ответ 4

Я добавляю это А, потому что я попался с причудливой версией этого, которая действительно заставила меня почесывать голову около часа, пока я не заметил основную причину. Моя загрузка терпела неудачу из-за многократного повторения этого формата

<path>/linit.o:(.rodata1.libs+0x50): multiple definition of `lua_lib_BASE'
<path>/linit.o:(.rodata1.libs+0x50): first defined here

Я оказался ошибкой в ​​магии Makefile, где у меня был список файлов C и использование vpath и т.д., поэтому компиляторы выберут их из правильного каталога в иерархии. Однако один файл C был повторен в списке, в конце одной строки и в начале следующего, поэтому загрузка gcc, сгенерированная make, имела файл .o дважды в командной строке. Durrrrh. Несколько определений были получены из нескольких экземпляров одного и того же файла. Компилятор игнорировал дубликаты, кроме статических инициализаторов!