Ich habe in einem Header eine inline-Funktion deklariert. Ein anderes Modul inkludiert diesen Header und ruft diese Funktion auf. Im Assembler-Listing sehe ich, dass die Funktion wirklich ge-inlined wird. Da der Compiler auch die Parameter kennt kann sie sogar fast vollständig wegoptimiert werden (2 Takte vs 65!). Mit meiner Lösung bin ich sehr zufrieden. Wollte allerdings noch testen wie sich das Ganze ohne Optimierung verhält. Allerdings compiliert mir mein Code mit -O0 garnicht erst: undefined reference to *** Aktueller avr-gcc. Hab auf die schnelle nichts gefunden. Aber inline müsste doch auch ohne Optimierung erfolgen? (Auch wenns hier wenig sinn macht, nur aus Interesse)
Bist du hobbymäßiger Ironie-Betreiber?? Deine *** ist exakt das einzige, was aus deinem Post hilfreich gewesen wäre. Oder... du nutzt die Delay-Routinen, aber keine Mathe/Floatingpoint-Lib... Rück raus mit dem Fehler oder es ***** :-P
> Deine *** ist exakt das einzige, was aus deinem Post hilfreich gewesen
wäre.
Was genau hilft dir, wenn du weist das meine Funktion fubarfubar123()
heißt?
@ Karlheinz: danke, das wars. Aber wieso?
inline sorgt ja dafür, dass ich, bei mehrfachen Einbindungen des
Headers, keinen redefinition-error bekomme.
Ok, ohne static wird das Symbol auchnoch exportiert, dadurch könnte eine
andere Kompiliereinheit per "extern" am Header vorbei diese Funktion
aufrufen. Ohne static muss der Compiler also auch einmal die
"Vollversion" meiner Funktion anlegen, sie könnte ja wo anders benutzt
werden. Soweit ist static hier ok!
Aber dieses "undefined reference" kann ich mir nicht erklären.
Leider geistert zu diesem Thema im Netz sehr viel Halbwissen :/
hui schrieb: > inline sorgt ja dafür, dass ich, bei mehrfachen Einbindungen des > Headers, keinen redefinition-error bekomme. Nein. Das macht "static". "inline" ist nur ein Hinweis an den Compiler, dass der Entwickler der Meinung war, dass diese Funktion sinnvoll inline erweiterbar sei. Der Compiler muss sich dieses Hinweises nicht annehmen (so, wie früher auch "register" nur ein Hinweis war). GCC inlinet die entsprechende Funktion, sofern sie seiner Meinung nach klein genug ist, und sofern die Optimierungen zugelassen sind. Die Idee dabei ist einfach, dass jemand, der ausdrücklich keine Optimierungen wünscht, in der Regel eine möglichst gute 1:1-Abbildung seines Quellcodes im Maschinencode sehen möchte. > Ok, ohne static wird das Symbol auchnoch exportiert, dadurch könnte eine > andere Kompiliereinheit per "extern" am Header vorbei diese Funktion > aufrufen. Ja. > Ohne static muss der Compiler also auch einmal die > "Vollversion" meiner Funktion anlegen, sie könnte ja wo anders benutzt > werden. Nein. Nicht der Compiler, sondern du. Du musst in einer der Übersetzungseinheiten noch eine ganz normale globale Funktion haben, auf die der Linker dann zurückgreifen kann. Woher zum Geier[tm] sollte denn der Compiler wissen, in welcher deiner vielen Übersetzungseinheiten er nun gerade die nicht-inline-Implementierung hinterlassen soll? Genau diese Implementierung fehlt dir aber jetzt, daher "undefined reference", denn durch die ausgeschalteten Optimierungen wird die Funktion ja nicht inline angelegt und stattdessen versuch, auf die globale Implementierung zurückzugreifen.
Jörg Wunsch schrieb: > Nein. Nicht der Compiler, sondern du. Du musst in einer der > Übersetzungseinheiten noch eine ganz normale globale Funktion haben, > auf die der Linker dann zurückgreifen kann. wenn die funktion in der Header datei als inline implementiert ist, dann ist sie doch in jeder Quelle wo die Header-Datei verwendet wird enthalten? Sie würde dann sogar in jeder übersetzungseinheit (wo dieser header vorhanden ist) vorhanden sein
Peter II schrieb: > Sie würde dann sogar in jeder übersetzungseinheit (wo dieser header > vorhanden ist) vorhanden sein Und, wie soll das gehen, ohne dass der Linker sich dann über eine Mehrfachdefinition des entsprechenden Namens beschwert? Ja, der Compiler könnte sie nur entweder in jeder Übersetzungsein- heit oder in keiner dieser global implementieren. Sich eine einzelne auszuwählen, ist ihm mangels geeigneter Kriterien (muss ja auch nicht alles zur gleichen Zeit compiliert werden) nicht möglich. Da eine Implementierung in jeder Einheit nicht möglich ist (wegen der dann auftretenden Mehrfachdefinitionen), bleibt nur die Variante, sie nirgends automatisch zu generieren, sondern die Entscheidung, wo er die globale Definition anlegt, dem Programmierer zu überlassen. Anders bei “static inline”: hier kann der Compiler ohne ein Risiko von Mehrfachdefinitionen in jeder Übersetzungseinheit eine Kopie hinterlegen, wenn er die Funktion nicht inline erweitert (und das tut er auch, was natürlich den Sinn von “inline” ins Gegenteil verkehrt; man hat dann viel Code, der trotzdem langsam ist).
>Und, wie soll das gehen, ohne dass der Linker sich dann über
eine Mehrfachdefinition des entsprechenden Namens beschwert?
Durch das inline?
Zumindest ein kurzer Test hat mich vorhin zu diesem Gedankengang
bewogen.
Funktion im Header ohne inline: klappt natürlich nicht, redefined
Funktion im Header, mit inline: klappt super!
-O0: undefined reference. Er sucht anscheinend eine Funktion ohne
inline, deswegen der Fehler
hui schrieb: >>Und, wie soll das gehen, ohne dass der Linker sich dann über > eine Mehrfachdefinition des entsprechenden Namens beschwert? > > Durch das inline? Du hast das nicht bis zu Ende gedacht. Unter welchem Namen soll der Compiler denn die N verschiedenen, nicht inline implementierten Kopien im Objektcode hinterlegen, sodass der Linker sie alle auflösen kann, es aber keine Mehrfachdefinitionen gibt? > Funktion im Header ohne inline: klappt natürlich nicht, redefined > Funktion im Header, mit inline: klappt super! Klar, solange er alle inline erweitert. Bei “extern inline” legt der Compiler ja keine zusätzliche globale Kopie an (wie wir schon festgestellt hatten). Solange er alle Aufrufe inline erweitern kann, werden diese auch nicht gebraucht. > -O0: undefined reference. Er sucht anscheinend eine Funktion ohne > inline, deswegen der Fehler Ja, die eine globale Kopie muss dann ohne “inline” stehen, logisch. Also so: foo.h:
1 | inline void foo(void) { PORTB = 42; } |
foo.c:
1 | #include "foo.h" |
2 | |
3 | /* das ist die globale Kopie */
|
4 | void foo(void) |
5 | {
|
6 | PORTB = 23; /* ja, die kann auch was ganz anderes machen ;-) */ |
7 | }
|
bar.c:
1 | #include "foo.h" |
2 | |
3 | void dosomething(void) |
4 | {
|
5 | /* ... */
|
6 | foo(); /* mit Optimierung wird foo() inline erweitert, ohne |
7 | wird dagegen das foo() aus foo.c gerufen */
|
8 | }
|
Wenn man sich stets angewöhnt, alle inline-Funktionen “static inline” zu deklarieren, ist man den Kuddelmuddel los. Eine “static” deklarierte Funktion bekommt ja keinen global gültigen Namen, sondern einen, der nur in der jeweiligen Übersetzungseinheit gültig ist. Damit gibt es auch dann keine Namenskollision, wenn der Compiler sich entschließt, das “inline” zu ignorieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.