Wie kann man mehrere Definitionen in C verhindern?

Lesezeit: 5 Minuten

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, gibt es die folgenden Fehler:

*path*\test.c|1|multiple definition of `_ test'|
obj\Debug\main.o:*path*\test.c|1|first defined here|

Es gibt keine Möglichkeit, dass ich test mehrfach definiere (obwohl ich nicht weiß, woher der Unterstrich kommt), und es scheint höchst unwahrscheinlich, dass die Definition irgendwie zweimal enthalten ist. Dies ist der gesamte Code, den es gibt.

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

Weiß jemand woran das liegt und was ich dagegen tun kann? Vielen Dank!

Benutzeravatar von mouviciel
mouviciel

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

  • Das erste Mal beim Kompilieren test.c selbst,
  • Das zweite Mal beim Kompilieren main.c was alle beinhaltet test.c Quelle.

Was Sie in Ihrem brauchen main.c um die zu verwenden test() Funktion ist eine einfache Deklaration, nicht ihre Definition. Dies wird erreicht, indem a test.h Header-Datei, die so etwas enthält wie:

void test(void);

Dadurch wird dem Compiler mitgeteilt, dass eine solche Funktion mit Eingabeparametern und Rückgabetyp existiert. Was diese Funktion macht (alles in { und } ) bleibt in Ihrem test.c Datei.

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

Ein letzter Punkt: Bei komplexeren Programmen werden Sie mit Situationen konfrontiert, in denen Header-Dateien mehrfach eingebunden werden können. Um dies zu verhindern, werden Header-Quellen manchmal von bestimmten Makrodefinitionen eingeschlossen, wie zum Beispiel:

#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED

void test(void);

#endif

  • Namen wie TEST.H die mit einem Unterstrich und einem Großbuchstaben beginnen, sind im C-Benutzercode illegal – sie sind den Compiler-Implementierern vorbehalten.

    anon

    23. März 2009 um 10:13 Uhr

  • Sie sollten Informationen über die Parameter von test() in der Header-Datei angeben, dh void test(); -> ungültiger Test (nichtig);

    – Aib

    24. März 2009 um 19:27 Uhr

  • You actually compile the source code of test.c twice: •The first time when compiling test.c itself, •The second time when compiling main.c which includes all the test.c source. und das wird als Antwort akzeptiert?? (Technisch wahr, aber es beantwortet kaum) Sie erfüllen jede Einheit einmal. Der Compiler löst, was er kann, in der aktuellen Datei auf und hinterlässt dann Hooks für den Linker. Es ist der Linker, der Ihren Aufruf auflöst test(); – und wird ein Problem haben, welches zu bestimmen test() meinst du eigentlich

    – Mawg sagt, Monica wieder einzusetzen

    23. Juni 2010 um 7:51 Uhr

  • @LeonixSolutions: Meine Antwort ist etwas ausführlicher als das, was Sie zitieren. Und es sieht so aus, als hätte es das Problem des OP gelöst.

    – mouviciel

    23. Juni 2010 um 9:54 Uhr

  • @Snusifer Es soll geprüft werden, ob die Header-Datei bereits eingebunden wurde, in diesem Fall soll sie nicht erneut eingebunden werden.

    – mouviciel

    13. Januar um 7:50 Uhr

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

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, das nur aus Deklarationen bestehen sollte, wie z. B. dem Funktionsprototypen:

void test(void);

Dies lässt den Compiler wissen, dass es existiert, wenn main.c kompiliert wird, aber der eigentliche Code befindet sich in test.c, dann test.o.

Es ist die Verknüpfungsphase, die die beiden Module miteinander verbindet.

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

Benutzeravatar von Kasprzol
Kasprzol

Sie sollten keine anderen Quelldateien (*.c) einschließen .c-Dateien. Ich denke, Sie möchten einen Header haben (.h) Datei mit der ERKLÄRUNG der Testfunktion und haben ihre DEFINITION in einer separaten .c Datei.

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

Murads Benutzeravatar
Murad

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

Löse wie folgt:

Funktionsprototyp-Deklarationen und globale Variablen sollten sich in der Datei test.h befinden, und Sie können globale Variablen nicht in der Header-Datei initialisieren.

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

Wenn Sie globale Variablen im Header initialisieren, wird der folgende Fehler angezeigt

Mehrfachdefinition von `_ test’| obj\Debug\main.o:Weg\test.c|1|zuerst hier definiert|

Nur Deklarationen von globalen Variablen in der Header-Datei, keine Initialisierung sollte funktionieren.

Ich hoffe es hilft

Prost

Einschließlich der Implementierungsdatei (test.c) bewirkt, dass es Ihrer main.c vorangestellt und dort und dann wieder separat kompiliert wird. Also die Funktion test hat zwei Definitionen – eine im Objektcode von main.c und einmal in dem von test.c, wodurch Sie eine ODR-Verletzung erhalten. Sie müssen eine Header-Datei erstellen, die die Deklaration von enthält test und füge es ein main.c:

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

Benutzeravatar der Community
Gemeinschaft

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

  • #include “test.c” entfernen
  • Erstellen Sie eine Datei test.h, die die Deklaration enthält:
    ungültiger Test ();
  • Fügen Sie die Datei test.h in main.c ein

Benutzeravatar von cwap
happ

Wenn Sie Visual Studio verwenden, können Sie auch “#pragma once” oben in der Headerdatei ausführen, um dasselbe zu erreichen wie das “#ifndef …”-Wrapping. Einige andere Compiler unterstützen es wahrscheinlich auch .. .. Tun Sie dies jedoch nicht 😀 Bleiben Sie beim #ifndef-Wrapping, um Compiler-übergreifende Kompatibilität zu erreichen. Ich wollte Sie nur wissen lassen, dass Sie #pragma auch einmal machen könnten, da Sie dieser Aussage wahrscheinlich ziemlich oft begegnen werden, wenn Sie den Code anderer Leute lesen.

Viel Glück damit

1411710cookie-checkWie kann man mehrere Definitionen in C verhindern?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy