Forum: Compiler & IDEs Inline Funktionen die Xte


von Simon K. (simon) Benutzerseite


Lesenswert?

Huhu,

Ich hab schon etwas hier und da gesucht, aber ich suche immernoch eine 
klare Aussage, wie ich dem Compiler sagen kann, dass Funktionsaufrufe 
einer Funktion IMMER geinlined werden soll und dass der Funktionskörper 
nicht einzeln übersetzt wird (weil er ja nie über einen CALL aufgerufen 
werden würde).

Mal findet man _inline_, dann inline, die einen sagen was von 
Optimierung O2 und wiederum der andere erzählt was von attributen, die 
das inlinen erzwingen. Alles habe ich in fast jeglicher Kombination 
ausprobiert. Meistens wird die Funktion aber immernoch mit CALL 
aufgerufen. Ein paar Ausdrücke wie zum Beispiel:
1
//Prototyp in .h File
2
inline void rtc_irq() __attribute__ ((always_inline));    
3
4
//Implementierung in .c File
5
inline void rtc_irq(void)
6
{ 
7
  currenttime++;
8
}

Geben zum Beispiel folgende Fehlermeldung:
1
../time.h:11: sorry, unimplemented: inlining failed in call to 'rtc_irq': function body not available
2
../main.c:189: sorry, unimplemented: called from here

Vielleicht verstehe ich nicht so ganz, wie der Compiler hier arbeitet. 
Dann würde ich vielleicht auch verstehen, wo sein Problem liegt.
Ich würde mich freuen, wenn hier mal einer der GCC Spezies unter die 
Arme greifen könnte ;) Vielen Dank

PS: Ich verwende den AVR-GCC

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Inlining wird -wenn ich es richtig verstehe- nicht vom Linker 
abgewickelt, daher muss eine dafür vorgesehene Funktion auch in der 
Headerdatei definiert (und nicht nur deklariert) werden.

Die von Dir geposteten Fehlermeldungen lassen jedenfalls darauf 
schließen.

Der Funktionsname jedoch lässt darauf schließen, daß Du da einen 
Interrupthandler hast ... wie stellst Du Dir bei dem das inlining vor?

von Matthias (Gast)


Lesenswert?

Inline Funktionen müssen kompletten im Header File implementiert werden, 
also nicht aufteilen in .h und .c

Das Inline sagt dem Compiler aber trotzdem nur, dass er es nach 
Möglichkeit inlinen soll. Wenns ihm nicht passt (zB weil die Funktion zu 
lange ist), wird ers aber trotzdem zu ner Funktion machen.

von Simon K. (simon) Benutzerseite


Lesenswert?

Den Code in die Headerdatei? Uff, das widerspricht irgndwie meinem 
Verständnis von guter C-Programmierung *g
Eine andere Möglichkeit gibt es nicht?

>Der Funktionsname jedoch lässt darauf schließen, daß Du da einen
>Interrupthandler hast ... wie stellst Du Dir bei dem das inlining vor?

Die Funktion wird in einem Interrupthandler aufgerufen. Deswegen heißt 
sie so :-). Bzw diese Funktion MUSS zyklisch im Hauptprogramm aufgerufen 
werden.

Danke für eure Antworten bisher.

von kosmonaut pirx (Gast)


Lesenswert?

hi,
in meinem verständnis zur ersten fehlermeldung:
versucht euch einmal in den compiler hineinzuversetzen. der gcc included 
eine header-datei beim bearbeiten einer c-datei. da steht der prototyp 
einer aufgerufenen routine als inline drin. was nun? er soll den code 
inlinen, aber es ist ja keiner da. weil dieser erst in einer fremden 
c-datei steckt. ergo fehler.
bye kosmo

von Karl H. (kbuchegg)


Lesenswert?

> Uff, das widerspricht irgndwie meinem
> Verständnis von guter C-Programmierung *g
> Eine andere Möglichkeit gibt es nicht?

Stell dir mal vor, du wärest der Compiler.

Du weist was inlinen bedeutet? Ein Aufruf einer
Funktion wird durch den Funktionsinhalt selbst
ersetzt.

So jetzt kommt dein grosser Auftritt als Compiler.

Compilier mal in Gedanken folgenden Code. Du brauchst
keinen Assembler Code erzeugen. Tue einfach nur so als ob.

Hier kommt der Code:

inline void foo( void );

int main()
{
  int i;

  for( i = 0; i < 10; ++i )
    foo();
}

Also dann compilier mal schön und dass du ja die
Funktion inlinest.
Wie, du kannst die nicht inlinen? Steht doch da, dass
du sie inlinen sollt.
Wie, du müsstest schon díe Funktion selbst sehen um
den Funktionsaufruf ersetzen zu können? Da ist doch
der Funktionsprototyp!
Wie, der reicht dir nicht?

Ist es jetzt klarer, was du zu tun hast?
Wenn du willst, dass der Compiler eine Funktion auch
inlinen kann, dann musst du ihm schon auch die Funktions-
definition selbst zeigen. Nur mit dem Prototypen alleine
kann der Compiler nichts anfangen, wenn er den Funktions-
aufruf durch den Funktionsinhalt ersetzen soll.

Wenn es dir widerstrebt, den Code in eine Datei mit
der Endung *.h zu setzen:
Dem Präprozessor ist es völlig Wurscht wie die Datei heist.
#include holt die angegebene Datei in den Text rein. Und wenn
du beim #include eine jpg Datei angibst, dann wird halt
vom Prärozessor die jpg Datei reingezogen.
Wenn es dir also widerstrebt die Datei iregendwas.h zu nennen,
dann nenne sie irgendwas.inc

#include "rtc_irq.inc"

und in rtc_irq.inc ist dann die vollständige Funktionsdefinition.
Das *.inc ändert nichts an der grundsätzlichen Vorgangsweise.
Es ist eigentlich nur dazu da um anzuzeigen, dass das eben
kein ganz normales Headerfile mit Protoypen ist. Nicht für den
Compiler, dem ist es egal wie die Datei heist; fur dich
als Programmierer.



von Simon K. (simon) Benutzerseite


Lesenswert?

Ich verstehe. Nungut, danke für diese ausführliche Beschreibung.

Dann wollen wir mal ;)

von Karl heinz B. (kbucheg)


Lesenswert?

Ein wesentliches Element zum Verständns warum manche Dinge
in C so sind wie sie sind, besteht darin, dass in C jedes
C File (im Fachjargon heist das eine 'Translation Unit')
unabhängig von allen anderen C Files kompiliert wird.

Das heist, wenn sich der Compiler ein File a.c vornimmt,
dann interessiert ihn nur dieses eine File. Selbst
wenn man, wie es beim gcc möglich ist, beim Compileraufruf
mehrere C Files zur compilierung angeben kann, so läuft
das nach dem Muster ab:
  das erste File kompiliern
  alle internen Tabellen des Compilers löschen
  nächtes File kompilieren
  alle internen Tabellen des Compilers löschen
  nächstes File ...

Der Compiler hat also gewissermassen Scheuklappen. Der
kümmert sich nur darum, was er in dieser einen Translation
Unit vorfindet. Wenn du im File a.c eine Funktion aufrufst
und diese Funktion in einem anderen File, b.c, enthalten
ist, kümmert ihn nicht die Bohne, wie dieses File b.c
aussieht. Solange a.c compiliert wird, weiss der Compiler
noch nicht einmal, dass b.c überhaupt existiert. Geschweige
denn welche Funktionen da drinn sind oder wie die Funktionen
aussehen.

Deswegen braucht man in C auch die Prototypen. Den es gilt
nach wie vor: Der Compiler muss bei der compilierung darüber
informiert werden, wass sich so ausserhalb des begrenzten
Sichtfeldes dieser einen Translation Unit abspielt. Wenn
ich eine Funktion aufrufen möchte, dann ist für den Compiler
am Ort des Aufrufs nur interessant:
  * gibt es diese Funktion überhaupt (könnte ja auch ein
    Tippfehler im Funktionsnamen sein)
  * welche Argumente nimmt diese Funktion. Anzahl und Typ
    müssen gleich sein. Beim Typ gibt es dann noch den Fall
    dass eventuell eine Typanpassung (sprich ein impliziter
    cast) gemacht werden muss
  * welchen Returnwert hat diese Funktion

All diese Informationen stecken im Prototypen drinnen. Das reicht
auch vollkommen aus um einen Aufruf einer Funktion zu übersetzen.
Ob es diese Funktion auch tatsächlich gibt und wie diese Funktion
tatsächlich implementiert ist, braucht der Compiler an dieser
Stelle nicht wissen. Das interessiert erst dann, wenn die
Translation Unit mit dieser Funktion drann kommt.

Nur: Beim inlinen wollen wir ja mehr. Wir wollen ja, dass
überhaupt kein Funktionsaufruf zustande kommt, sondern der
Quelltext der Funktion an der Stelle des Aufrufs eingesetzt
wird. Und dazu muss der Compiler selbstverständlich den Quelltext
auch sehen können. Daraus folgt aber wiederrum, dass der Quelltext
in irgendeiner Form in die Translation Unit hineingezogen werden
muss.




von Simon K. (simon) Benutzerseite


Lesenswert?

Hallo Karl Heinz,
Soweit versteh ich das. Also übernimmt das Inlinen der Compiler und 
nicht der Linker (wie schon erwähnt).

Macht ja auch irgendwo Sinn, weil der Linker ja dann Funktionsaufrufe 
wieder löschen müsste.

Naja, nochmal Danke für die Erläuterungen.

von Karl heinz B. (kbucheg)


Lesenswert?

> Also übernimmt das Inlinen der Compiler und
> nicht der Linker (wie schon erwähnt).

Bis vor kurzem hätte ich gesagt: Ja das stimmt.

Aber mitlerweile gibt es auch Linker, die inlineing
Aufgaben übernehmen können. Das ändert aber nicht
wirklich was am Prinzip. Konzeptionell bleibt
in C alles beim Alten, selbst wenn der Linker das
inlining übernehmen würde.


von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bitte uebrigens als "static inline" deklarieren.  Dann eruebrigt sich
(zusammen mit der Unterbringung im .h-File) meist auch das
__attribute__((always_inline)).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.