Problem mit Inline in header

#4315678
Lesenswert?

Hallo zusammen

Ich habe in C eine Inline Definierung in einem Header.
Im main.c habe ich das Headerfile eingebunden. Wenn ich jedoch 
kompilieren will, zeigt es mir an, dass es mehrmals definiert ist. 
Verschiebe ich die Definition jedoch ins main.c, ist der Code 
kompilierbar.

Danke für Lösungsansätze.

MfG
#4315769
Lesenswert?

Sebastian V. schrieb:
> Die Fehlermeldungen sind offensichtlich vom Compiler also wirds ein
> Problem wegen fehlender Include Guards sein.

Nop
multiple definition" ist immer vom Linker.

Da fehlt ein 'static' vorm 'inline'.

Ohne wird der Compiler auf jeden Fall auch eigenständige 
Implementierungen für die Funktionen erzeugen, weil er nicht davon 
ausgehen kann, dass sie quer durch das Programm überall geinlined 
werden.
Mit static kann er davon ausgehen, dass dem so ist.
#4315803
Lesenswert?

Karl H. schrieb:
> Nop
> multiple definition" ist immer vom Linker.
>
> Da fehlt ein 'static' vorm 'inline'.

Ah hab mich von den Zeilennummern verwirren lassen. Wenn man nicht mit 
Debug Informationen Compiliert kriegt man nicht so schön Ausgaben.

Trotzdem ist es ein merkwürdiger Fehler vom Compiler. Inline Funktionen 
im Header sind korrekt und sollten auch ohne static davor compilieren 
(tun sie bei mir auch).
#4315817
Lesenswert?

Sebastian V. schrieb:
> Karl H. schrieb:
>> Nop
>> multiple definition" ist immer vom Linker.
>>
>> Da fehlt ein 'static' vorm 'inline'.
>
> Ah hab mich von den Zeilennummern verwirren lassen. Wenn man nicht mit
> Debug Informationen Compiliert kriegt man nicht so schön Ausgaben.
>
> Trotzdem ist es ein merkwürdiger Fehler vom Compiler. Inline Funktionen
> im Header sind korrekt und sollten auch ohne static davor compilieren
> (tun sie bei mir auch).

Compilieren tun sie.
Das ist auch nicht das Problem.

Aber: da der Compiler nicht davon ausgehen kann, dass an allen Stellen 
geinlined wird, muss er auch eine freistehende Defintion dieser Funktion 
erstellen. Du könntest dich ja aus einem ganz anderen C-File mittels 
explizitem 'extern' auf diese Funktion beziehen.

Ein 'static' davor begrenzt aber den Scope dieser Funktion auf jeden 
Fall auf das C-File, in welches diese inline Definition hineingezogen 
wurde. D.h. in diesem Fall ist es prinzpiell nicht möglich, dass sich 
irgendwelcher anderer Code mittels 'extern' auf diese Funktion beziehen 
könnte. Der Compiler kennt weiss also, dass in diesem Fall er beim 
Compilieren dieses einen C-Files alle Stellen gesehen hat, an der diese 
Funktion benutzt wurde. Und da er die alle geinlined hat, braucht es die 
freistehende Funktion nicht.

main.c
1
extern void bar();
2

3
inline void foo()
4
{
5
  mach was ....
6
}
7

8
int main()
9
{
10
  foo();   // dieser Aufruf wird geinlined
11
  bar();
12
}

help.c
1
extern void foo();
2

3
void bar
4
{
5
  foo();   // aber dieser Aufruf nicht. Daher muss es neben der
6
           // direkten Ersetzung in main.c auch noch eine tatsächlich
7
           // aufrufbare Version der Funktion geben.
8
}

Das ist das eigentliche Problem, wie es dazu kommt, dass der Compiler 
bei jedem #include (mit den inline-Funktionen) in jeder Compilation-Unit 
eine weitere Version der Funktion erzeugen muss.

Und nochmal:
Der Fehler stammt nicht vom Compiler sondern vom Linker, der bei der 
Endmontage der Einzelteile bemerkt, dass es eine (tatsächliche) Funktion 
dieses Namens ein paar mal gibt. In jedem C-File, welches vom Compiler 
einzeln übersetzt wurde, sind dieselben Funktionen jedesmal als 
tatsächlich aufrufbare Funktionen erneut angelegt worden.
#4315842
Lesenswert?

Jörg W. schrieb:
> Nein.  C99-Semantik.

Sicher? Ich habe gerade nochmal rumgespielt und ich kann das Problem vom 
TO nur nachvollziehen wenn ich mit -std=gnu89 compiliere. Mit -std=c99 
und -std=c11 erhalte ich statt "multiple definition" ein "undefined 
reference to" Fehler beim Linken.

Der C99 Standard sagt dazu:
If all of the file scope declarations for a function in a translation 
unit include the inline function specifier without extern, then the 
definition in that translation unit is an inline definition. An inline 
definition does not provide an external definition for the function, 
[...]

Wenn ich das richtig verstehe, dann besagen diese Zeile das in dem Fall 
vom TO, also nur inline im Header, KEINE externe Definition 
bereitgestellt wird und ich damit auch keinen "multiple definition" 
Fehler kriege. Stattdessen kriege ich "undefined reference to" weil gar 
nichts extern definiert wird, sofern man das nicht einmal explizit 
macht.
#4315853
Lesenswert?

Karl Heinz behauptet aber auch, dass bei jeder inline Definition eine 
externe Definition erzeugt wird:

Karl H. schrieb:
> Das ist das eigentliche Problem, wie es dazu kommt, dass der Compiler
> bei jedem #include (mit den inline-Funktionen) in jeder Compilation-Unit
> eine weitere Version der Funktion erzeugen muss.

Das scheint aber auch nur auf die GNU 89 Variante von C zuzutreffen.

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