wake-up-neo.com

Wie vermeide ich Mehrfachdefinitionen in C?

Ich bin ein C-Neuling und habe gerade versucht, eine Konsolenanwendung mit Code :: Blocks zu schreiben. Hier ist der (vereinfachte) Code: main.c:

#include <stdio.h>
#include <stdlib.h>
#include "test.c" // include not necessary for error in Code::Blocks

int main()
{
    //t = test(); // calling of method also not necessary
    return 0;
}

test.c:

void test() {}

Wenn ich versuche, dieses Programm zu erstellen, werden die folgenden Fehler angezeigt:

 * path *\test.c | 1 | mehrfache Definition von `_ test '| 
 obj\Debug\main.o: * path *\test.c | 1 | zuerst hier definiert | 

Auf keinen Fall kann ich Tests mehrfach definieren (obwohl ich nicht weiß, woher der Unterstrich kommt), und es ist sehr unwahrscheinlich, dass die Definition zweimal enthalten ist. Das ist der ganze Code, den es gibt.

Ich habe ausgeschlossen, dass dieser Fehler auf einen Namenskonflikt mit anderen Funktionen oder Dateien zurückzuführen ist, die als test oder test.c bezeichnet werden. Beachten Sie, dass sich die mehrfache und die erste Definition in derselben Zeile in derselben Datei befinden.

Weiß jemand, was das verursacht und was ich dagegen tun kann? Vielen Dank!

38
Jordi

Sie kompilieren den Quellcode von test.c Tatsächlich zweimal:

  • Das erste Mal, wenn test.c Selbst kompiliert wird,
  • Das zweite Mal beim Kompilieren von main.c, Das die gesamte test.c - Quelle enthält.

Was Sie in Ihrem main.c Brauchen, um die Funktion test() zu verwenden, ist eine einfache Deklaration, nicht deren Definition. Dies wird durch Einfügen einer test.h - Headerdatei erreicht, die etwa Folgendes enthält:

void test(void);

Dadurch wird der Compiler darüber informiert, dass eine solche Funktion mit Eingabeparametern und Rückgabetyp vorhanden ist. Was diese Funktion macht (alles in { Und }), Bleibt in Ihrer test.c - Datei.

Ersetzen Sie in main.c #include "test.c" Durch #include "test.h".

Ein letzter Punkt: Da Ihre Programme komplexer sind, werden Sie mit Situationen konfrontiert, in denen Header-Dateien möglicherweise mehrmals enthalten sind. Um dies zu verhindern, werden Header-Quellen manchmal von bestimmten Makrodefinitionen eingeschlossen, z.

#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED

void test(void);

#endif
84
mouviciel

Der Unterstrich wird vom Compiler dort abgelegt und vom Linker verwendet. Der grundlegende Pfad lautet:

main.c
test.h ---> [compiler] ---> main.o --+
                                     |
test.c ---> [compiler] ---> test.o --+--> [linker] ---> main.exe

Ihr Hauptprogramm sollte also die Header-Datei für das Testmodul enthalten, die nur aus Deklarationen bestehen sollte, wie zum Beispiel dem Funktionsprototyp:

void test(void);

Auf diese Weise wird dem Compiler mitgeteilt, dass er vorhanden ist, wenn main.c kompiliert wird, der eigentliche Code jedoch in test.c und dann in test.o enthalten ist.

Es ist die Verbindungsphase, die die beiden Module miteinander verbindet.

Indem Sie test.c in main.c einfügen, definieren Sie die test () - Funktion in main.o. Vermutlich verknüpfen Sie dann main.o und test.o, die beide die Funktion test () enthalten.

26
paxdiablo

Sie sollten keine anderen Quelldateien (* .c) in .c-Dateien) einfügen. Ich denke, Sie möchten eine Headerdatei ( .h) mit der DECLARATION of test-Funktion und der DEFINITION in haben eine separate .c-Datei.

Der Fehler wird durch mehrere Definitionen der Testfunktion verursacht (eine in test.c und eine andere in main.c)

10
Kasprzol

Ich hatte ein ähnliches Problem und habe es folgendermaßen gelöst.

Lösen Sie wie folgt:

Funktionsprototypdeklarationen und globale Variablen sollten sich in der Datei test.h befinden, und Sie können die globale Variable in der Headerdatei nicht initialisieren.

Funktionsdefinition und Verwendung der globalen Variablen in der Datei test.c

wenn Sie globale Variablen im Header initialisieren, tritt der folgende Fehler auf

mehrfachdefinition von `_ test '| obj\Debug\main.o: Pfad\test.c | 1 | hier zuerst definiert |

Nur Deklarationen globaler Variablen in der Header-Datei, die nicht initialisiert werden sollen, sollten funktionieren.

Ich hoffe es hilft

Prost

6
Murad

Wenn Sie Visual Studio verwenden, können Sie auch "#pragma once" oben in der Headerdatei ausführen, um das Gleiche wie beim "#ifndef ..." - Wrapping zu erreichen. Einige andere Compiler unterstützen dies wahrscheinlich ebenfalls. Tun Sie dies jedoch nicht: D Halten Sie sich an den # ifndef-Zeilenumbruch, um Kompatibilität zwischen Compilern zu erreichen. Ich wollte Sie nur wissen lassen, dass Sie auch einmal #pragma machen können, da Sie diese Aussage wahrscheinlich ziemlich oft treffen werden, wenn Sie den Code anderer Leute lesen.

Viel Glück damit

4
cwap

Das Einfügen der Implementierungsdatei (test.c) Bewirkt, dass sie Ihrer main.c vorangestellt und dort und dann erneut separat ausgeführt wird. Die Funktion test hat also zwei Definitionen - eine im Objektcode von main.c Und eine in der von test.c, Was zu einer ODR-Verletzung führt. Sie müssen eine Header-Datei mit der Deklaration von test erstellen und in main.c Einfügen:

/* test.h */
#ifndef TEST_H
#define TEST_H
void test(); /* declaration */
#endif /* TEST_H */
4
dirkgently

Wenn Sie Ihrem Code :: Blocks-Projekt test.c hinzugefügt haben, wird die Definition zweimal angezeigt - einmal über das # include und einmal über den Linker. Du musst:

  • entferne das #include "test.c"
  • erstellen Sie eine Datei test.h, die die Deklaration enthält: void test ();
  • fügen Sie die Datei test.h in main.c ein

4
anon