C: Eine Funktion mehrmals in einem Projekt verwenden

Gast #790470
Lesenswert?
• ▲
▼
Hallo,

ich habe hier ein mieses Linker-Problem.
Ich habe eine Funktion test(), die ich in test.c geschrieben habe. Im 
Header-File test.h steht lediglich der Protyp etwa:

#ifndef TEST_H
#define TEST_H


// --- prototypes
void test(void);

#endif



Die Funktion wird jetzt von zwei *.c-Dateien aus aufgerufen. (timer.c, 
pwm.c)
Sie inkludieren beide die test.h, logisch.

Doch irgendwas läuft da noch faul. Einmal inkludieren funktioniert aber. 
Mehrmals leider nicht.

ERROR: The following symbols referenced could not be resolved...

Kann ich das irgendwie mit dem Schlüsselwort extern umgehen oder wie 
löse ich das Problem?

DANKE schon einmal.
Gast #790483
Lesenswert?
• ▲
▼
>Gehört das extern denn auch mit in die test.c oder nur bei den
>Prototypen?

Ich mache das so, dass ich alle Prototypen in einer header-Datei packe 
und diese dann "inkludiere". Jeder Prototyp bekommt dann extern. So hast 
du wenigstens alle Funktionen an einem Ort versammelt.
Gast #790515
Lesenswert?
• ▲
▼
Beispiel:

#include "define_prototypes.h"

extern void timer_init(void);

-------------------------

Datei main.c

void main(void)
{
    timer_init();
}

---------------------------

Datei init.c

void timer_init(void)
{
...
}

So machst du das z.B. auch, wenn du delays einbauen möchtest. Dann 
definierst du z.B. in der Datei delay.c deine Funktion, packst sie in 
die prototypen-Datei mit extern rein und inkludierst in jedem c-File 
diese Datei. Dann kannst du sie überall aufrufen.
Gast #790522
Lesenswert?
• ▲
▼
PS: Ohne Extern erhälst du die Fehlermeldung "implicit declaration of 
function...". Dein Compiler kann nicht "riechen", wo sich deine Funktion 
befindet. Somit ist extern hier essentiell wichtig.
#790523
Lesenswert?
• ▲
▼
Das extern an dieser Stelle schadet zwar nicht, bringt
aber auch nichts.
Der Compiler kann auch so erkennen das es sich um eine
Deklaration handelt.

Wenn schon, dann mach es richtig:

Datei: Proto.h
*************
1
#ifndef PROTO_H
2
#define PROTO_H
3

4
void timer_init(void);
5

6
#endif

Datei main.c
************
1
#include "Proto.h"
2

3
int main(void)
4
{
5
    timer_init();
6
}

Datei: init.c
*************
1
#include "Proto.h"
2

3
void timer_init(void)
4
{
5
...
6
}
(Firma: OpenKNX) #790527
Lesenswert?
• ▲
▼
extern ist hier fehl am Platz, dat hilft nix. Welcher Compiler?
Denn bei Funktionsprototypen ist ja extern idR eh default.


It can be used as a stylistic hint to indicate that the
function's definition is probably in another source file, but
there is no formal difference between

                extern int f();

        and

                int f();

References: ANSI Sec. 3.1.2.2, Sec. 3.5.1; ISO Sec. 6.1.2.2,
Sec. 6.5.1; Rationale Sec. 3.1.2.2; H&S Secs. 4.3,4.3.1 pp. 75-
6.

Ich tippe auch auf Linker Problem
#790545
Lesenswert?
• ▲
▼
Sven

Nochmal: Gast löst ein Problem, welches nicht existiert.

Dein Problem besteht höchst wahrscheinlich darin, dass du
vergessen hast, das zweite Source Code File deiner IDE oder
deinem makefile bekannt zu machen.
Alternativ könnte es auch ein simpler Tippfehler im Funktions-
namen sein.

'undefined reference' ist eine Fehlermeldung vom Linker und
nicht vom Compiler.
Gast #790548
Lesenswert?
• ▲
▼
>Das ist absolut richtig was du da schreibst, doch irgendwie ist mein
>Linker echt zu dumm. Mit extern vor jedem PROTOTYP hat nix gebracht.
>Echt übel.

Hast du ein selbst geschriebenes Make-File? Ein Linker kann nicht zu 
dumm sein. Zeig mal bitte dein Make-File.
#790552
Lesenswert?
• ▲
▼
Sir Sydom wrote:
> extern ist hier fehl am Platz, dat hilft nix. Welcher Compiler?
> Denn bei Funktionsprototypen ist ja extern idR eh default.
Rüchtüch. extern hat nur bei Variablen einen Effekt, weil der Compiler 
da nicht selber zwischen Deklaration und Definition unterscheiden kann. 
Bei Funktionsprototypen ist extern ziemlich sinnfrei.
#790559
Lesenswert?
• ▲
▼
Gast wrote:
>>Mit Verlaub: Aber du verzapfst Blödsinn.
>
> Mit Verlaub, du musst nicht deine primitive Geisteshaltung zeigen und
> jeden gleich anpissen.

Es geht nicht um anpissen.
Es geht darum, dass Sven ein ganz anderes Problem hat, als das
was du die ganze Zeit zu lösen versuchst (und das in Wirklichkeit
kein Problem ist).
Und dein Erklärung von 'extern' zeigt eigentlich nur, dass du
selbst 'extern' nicht richtig verstanden hast.

> Zeig mal bitte dein Make-File.

Endlich gehts in die richtige Richtung.
#790587
Lesenswert?
• ▲
▼
Was ist der Unterschied zwischen
1
int dummy1(void);

und
1
int dummy2;

?

Das erste ist ein PROTOTYP. Das heist das sagt dem Compiler "du, da 
fliegt irgendwo 'ne Funktion rum die so aussieht - die Funktion selber 
liegt aber ganz woanders, daher sag ich dir mal wie die aufgerufen 
werden muss".

Das zweite ist kein Prototyp. Da wird eine Variable definiert, so wie 
man eine Funktion implementiert.
Da die Variable aber auch woanders liegen kann, braucht man auch für 
Variablen Prototypen - das sieht dann so aus:
1
extern int dummy2;


Also merke:
1
int dummy1(void);
2
extern int dummy2;

gehören zusammen, und
1
int dummy1()
2
{
3
  // ...
4
}
5

6
int dummy2;

gehören auch zusammen.
Moderator Persönliche Seite #790595
Lesenswert?
• ▲
▼
I_ H. wrote:

> Das erste ist ein PROTOTYP.

Zufällig auch das. ;)  In erster Linie ist es aber eine
Funktionsdeklaration.  Man kann eine solche auch ohne einen
Prototypen schreiben:

int dummy1();

Das Schlüsselwort "extern" ist bei Funktionsdeklarationen
wahlfrei, da der Compiler aus dem Kontext (rundes Klammernpaar
mit abschließendem Semikolon) ableiten kann, dass es sich um
eine Funktionsdeklaration handelt.

> Das zweite ist kein Prototyp.

Kann es auch nicht sein, da das Wort "Prototyp" in C nur für
Funktionen benutzt wird.

> Da wird eine Variable definiert, so wie
> man eine Funktion implementiert.

Ja.

> Da die Variable aber auch woanders liegen kann, braucht man auch für
> Variablen Prototypen - das sieht dann so aus:
1
extern int dummy2;

Das ist richtig geschrieben, aber falsch bezeichnet.  Es ist
eine Variablendeklaration.  (Zur Erinnerung: das andere da oben
war eine Variablendefinition.)
Moderator Persönliche Seite #790633
Lesenswert?
• ▲
▼
Die begriffliche Unterscheidung zwischen Deklaration, Definition und
Prototyp halte ich dennoch für essenziell genug, als dass eine
(öffentlich lesbare und daher potenziell von anderen als Referenz
benutzte) Erklärung dafür korrekt sein sollte.  Es ist ja nicht nur,
dass man das Prinzip verstanden haben muss.  Wenn man diese drei
Begriffe gedanklich nicht richtig sortiert, wird man zu gegebener
Zeit aus einer möglichen Fehlermeldung des Compilers (wie bspw.
"Function declaration is not a prototype") absolut nicht schlau.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren