www.mikrocontroller.net

Forum: Compiler & IDEs Inline Funktionen die Xte


Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
//Prototyp in .h File
inline void rtc_irq() __attribute__ ((always_inline));    

//Implementierung in .c File
inline void rtc_irq(void)
{ 
  currenttime++;
}

Geben zum Beispiel folgende Fehlermeldung:
../time.h:11: sorry, unimplemented: inlining failed in call to 'rtc_irq': function body not available
../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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: kosmonaut pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.



Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe. Nungut, danke für diese ausführliche Beschreibung.

Dann wollen wir mal ;)

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.




Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl heinz Buchegger (kbucheg)
Datum:

Bewertung
0 lesenswert
nicht 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.


Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.