2009-03-23 11 views
25

Jestem początkującym programistą i właśnie próbowałem napisać aplikację konsolową z Code :: Blocks. Oto (uproszczony) Kod: main.c:Jak zapobiec wielu definicji w 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() {} 

Kiedy próbuję zbudować ten program, daje następujące błędy:

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

Nie ma mowy, żebym mnożył definiując test (chociaż nie wiem skąd pochodzi podkreślenie) i wydaje się bardzo mało prawdopodobne, że definicja jest w jakiś sposób zawarta dwukrotnie. To jest cały kod.

Wykluczyłem, że ten błąd spowodowany jest konfliktem nazw z innymi funkcjami lub plikami, nazywane testami lub test.c. Zwróć uwagę, że wielokrotność i pierwsza definicja znajdują się w tym samym wierszu w tym samym pliku.

Czy ktoś wie, co jest przyczyną tego i co mogę z tym zrobić? Dzięki!

Odpowiedz

66

rzeczywiście skompilować kod źródłowy test.c dwukrotnie:

  • Po raz pierwszy podczas kompilacji samego test.c,
  • Po raz drugi podczas kompilacji main.c który obejmuje wszystkie źródła test.c.

To, czego potrzebujesz w swoim main.c, aby móc korzystać z funkcji test(), jest prostą deklaracją, a nie jej definicją. Osiąga się to poprzez włączenie pliku test.h nagłówka, który zawiera coś takiego:

void test(void); 

ten informuje kompilator, że istnieje taka funkcja z parametrami wejściowymi i typ zwracany. Funkcja ta (wszystko wewnątrz { i }) pozostaje w pliku test.c.

W pliku main.c należy wymienić #include "test.c" przez #include "test.h".

Ostatni punkt: w przypadku, gdy twoje programy są bardziej złożone, będziesz musiał zmierzyć się z sytuacjami, w których pliki nagłówkowe mogą być zawarte kilka razy. Aby temu zapobiec, źródła nagłówka są niekiedy otoczone konkretnych definicji makr, takich jak:

#ifndef TEST_H_INCLUDED 
#define TEST_H_INCLUDED 

void test(void); 

#endif 
+0

Nazwy takie jak _TEST.H_, które zaczynają się od znaku podkreślenia i dużej litery są niedozwolone w kodzie użytkownika C - są zarezerwowane dla implementatorów kompilatorów. –

+0

Powinieneś podać informacje o parametrach do przetestowania() w pliku nagłówkowym, tj. Void test(); -> void test (void); – aib

+0

Po prostu wziąłem interfejs sugerowany w pytaniu, ale masz rację: aktualizuję odpowiedź. – mouviciel

9

Nie należy dołączać innych plików źródłowych (* .c) w plikach .c w postaci . Myślę, że chcesz mieć nagłówek ( .h) z funkcją DEKLARACJA funkcji testowej i mieć DEFINICJĘ w oddzielnym pliku .c.

Błąd spowodowany jest wieloma definicjami funkcji testowej (jeden w test.c i innych w main.c)

4

w tym pliku wdrażania (test.c) powoduje to być dołączany do main.c i przestrzegane tam, a następnie ponownie osobno. Tak więc funkcja test ma dwie definicje - jedną w kodzie obiektowym main.c i jedną w kodzie obiektowym test.c, która daje naruszenie ODR. Musisz utworzyć plik nagłówka zawierającego deklarację test i umieścić go w main.c:

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

Jeśli dodałeś test.c do kodeksu :: Blocks projektu, definicja będą widoczne dwa razy - raz za pośrednictwem #include i raz przez linker. Trzeba:

  • usunąć #include "test.c"
  • stworzyć test.h pliku zawierającego deklarację: void test();
  • obejmują test.h pliku w main.c

20

podkreślenia jest tam umieszczone przez kompilator i używane przez łącznik. Podstawowym ścieżka to:

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

Więc twój główny program powinien zawierać nagłówek pliku dla modułu testowego, który powinien składać się tylko z deklaracji, takich jak prototyp funkcji:

void test(void); 

Dzięki temu kompilator wiem, że istnieje podczas kompilacji main.c, ale rzeczywisty kod znajduje się w pliku test.c, a następnie test.o.

Jest to faza łączenia, która łączy ze sobą dwa moduły.

Włączając test.c do main.c, definiujesz funkcję test() w main.o. Prawdopodobnie łączysz main.o i test.o, z których oba zawierają test funkcji().

+1

Up-głosowania na ładnym rysunkiem. –

+1

Kolejne głosowanie w górę za ładny diagram sztuki ASCII. –

4

Jeśli używasz Visual Studio można też zrobić „#pragma once” na górze headerfile aby osiągnąć to samo jako "#ifndef ..." - zawijanie. Niektóre inne kompilatory prawdopodobnie również to obsługują .. .. Jednak nie rób tego: D Przyklej z # ifndef-wrapping, aby osiągnąć kompatybilność między kompilatorami. Chciałem tylko poinformować, że możesz również zrobić #pragma raz, ponieważ prawdopodobnie będziesz pewnie spotykał się z tym stwierdzeniem podczas czytania kodu innych ludzi.

Powodzenia z nim

5

Miałem podobny problem i rozwiązałem go po drodze.

rozwiązać następująco:

deklaracje prototyp funkcji i zmienna globalna powinna być w test.h pliku i nie można zainicjować zmienną globalną w pliku nagłówka.

Definicja funkcji i wykorzystanie zmiennej globalnej w pliku test.c

jeśli inicjalizacja zmiennych globalnych w nagłówku będzie mieć następujący błąd

stwardnienie definicja testu `_ '| obj \ Debug \ main.o: ścieżka \ test.c | 1 | pierwsza definicja tutaj |

Po prostu deklaracje zmiennych globalnych w pliku nagłówkowym inicjalizacja nie powinna działać.

Nadzieja pomaga

Cheers

Powiązane problemy