Adresse einer Funktion
-
Hey Leute,
mir ist eben etwas aufgefallen, was ich sehr komisch finde. Wieso wird die Adresse einer Funktion immer mit 1 angeben. Wenn ich die Adresse ausgeben will, erhalte ich nur eine 1 und der Compiler warnt mich, da es immer als eine 1 ausgewertet wird.
Kann mir vielleicht jemand erklären warum das so ist bzw was für einen Sinn das hat?Schonmal vielen Dank
Lg freeG
-
Machs doch so: http://ideone.com/0yLio
-
Häh?
Vielleicht wird die Adresse beim Vergleich implizit nach 1 (true) konvertiert, aber die Adresse einer Funktion sollte so gut wie nie 1 sein. Zeig doch mal deinen Codeschnipsel.
-
Also so wollt ich das machen, dachte zumindest das es so geht:
void func() { cout << "func" << endl; } int main() { cout << std::hex << func << endl; // oder cout << std::hex << &func << endl; }Jedoch erhalte ich dann nur eine 1 bzw 0x1 und der Compiler meldet immer eine Auswertung als true.
Ist mein Versuch die Adresse zu ermitteln etwa falsch?Lg freeG
-
Sieht so aus, als würde bei der Overload Resolution der
<<operator(bool)aufgerufen. Und die Adresse der Funktion als bool ist natürlich true bzw. 1. Probiere mal casten in void*.
-
&func ist korrekt, func tut´s aber auch. Bei mir wird bei
#include <iostream> void func() { } int main() { std::cout << std::hex << func << std::endl; std::cout << std::hex << &func << std::endl; }zweimal 40117c ausgegeben.
-
ostream::operator<<hat keine überladene Funktion für Pointer, bzw. nur
ostream& operator<< (const void* val );und einen Funktionszeiger kann ja nicht nach void* konvertiert werden, also wird der Compiler wohl eine bool-Konvertierung durchführen.
-
Also unter CodeBlocks mit GCC kam auch mit
cout << hex << &func << endl;immer nur eine 1 heraus, mit MSVC, kommt jedoch bei
cout << hex << &func << endl; cout << hex << func << endl; cout << &func << endl; cout << func << endl;immer das gleiche heraus, nämlich eine Speicheradresse. Da versteht dann der GCC wohl was falsch oder?
Was mir aber aufgefallen ist, wieso hat auch eine Inline-Funktion einen Speicherplatz? Wird also für eine Inline-Funktion trotzdem Speicher reserviert und sie wird auch gespeichert, allerdings wird dort nie hingesprungen, sondern es wird eben vom Compiler geinlint( klar, er muss nicht inlinen, ich mein nur für den Fall dass er es macht)?
Lg freeG
-
DocShoe schrieb:
&func ist korrekt, func tut´s aber auch. Bei mir wird bei
#include <iostream> void func() { } int main() { std::cout << std::hex << func << std::endl; std::cout << std::hex << &func << std::endl; }zweimal 40117c ausgegeben.
Welchen Compiler verwendest du?
-
fr33g schrieb:
Da versteht dann der GCC wohl was falsch oder?
Ist es nicht vielmehr so, dass der MSVC irgendwas anderes macht. Wenn der Standard keine passende, überladene ostream::operator<< Funktion bietet, wie soll dann eine aufgerunfen werden? Ich finde das Verhalten vom GCC absolut nachvollziehbar.
-
Gugelmoser schrieb:
ostream::operator<<hat keine überladene Funktion für Pointer, bzw. nur
ostream& operator<< (const void* val );und einen Funktionszeiger kann ja nicht nach void* konvertiert werden, also wird der Compiler wohl eine implizite bool-Konvertierung durchführen.
Sorry, hatte deine Post zu spät gesehen.
Wenn ich beim GCC in allen 4 Zeilen, meines vorherigen Codes, anstatt func bzw &func das ganze mittels reinterpret_cast zu void* caste, kommt auch bei allen 4 Versionen die gleiche Speicheradresse heraus.Beim MVSC geht es allerdings ohne zu casten, hat er dann weiter überladene <<-Operatoren überladen oder wieso geht es dort?
std::hex benötige ich allerdings wie gesagt generell nicht, das Ergebnis wird auch so in hex ausgegeben( beim GCC mit dem cast zum void* und beim MSVC einfach so)
Lg freeG
-
Gugelmoser schrieb:
fr33g schrieb:
Da versteht dann der GCC wohl was falsch oder?
Ist es nicht vielmehr so, dass der MSVC irgendwas anderes macht. Wenn der Standard keine passende, überladene ostream::operator<< Funktion bietet, wie soll dann eine aufgerunfen werden? Ich finde das Verhalten vom GCC absolut nachvollziehbar.
Jetzt war mein Post wieder zu langsam...ich meinem letzen Post habe ich dir ja zugestimmt;-)
Aber was ist denn jetzt eg wegen dem inline und wie kann es eg kommen, dass der MVSC was macht, was eg nicht so vom Standard vorgesehen ist?
Lg freeG
-
fr33g schrieb:
... reinterpret_cast zu void* caste, kommt auch bei allen 4 Versionen die gleiche Speicheradresse heraus.
Ok, mittels reinterpret_cast. Aber wir wissen ja, dass der reinterpret_cast wirklich alles mögliche hin und her biegen kann.

fr33g schrieb:
Beim MVSC geht es allerdings ohne zu casten, hat er dann weiter überladene <<-Operatoren überladen oder wieso geht es dort?
Hmm, weiß ich nun auch nicht. Müssen wir mal warten, ob die Profis nachher kurz etwas dazu sagen.

-
Hoffentlich, weil das interessiert mich jetzt schon

Außerdem würde mich auch wie gesagt interessieren, wie das bei Inline-Funktionen ist, ob die also wirklich auch im Arbeitsspeicher untergebracht werden.
Lg freeG
-
fr33g schrieb:
Außerdem würde mich auch wie gesagt interessieren, wie das bei Inline-Funktionen ist, ob die also wirklich auch im Arbeitsspeicher untergebracht werden.
Steht eigentlich alles im Effektive C++:
- inline ist keine zwingende Anweisung, sondern ein Ratschlag. Der Compiler muss sich nicht dran halten.
- Wenn er es inline macht, dann ist die Funktion nicht im Arbeitsspeicher untergebracht, es sei denn man nimmt ihre Adresse. inline-Funktionen verhalten sich ja wie echte Funktionen.
- Die anderen Aufrufe werden aber dennoch geinlined
- Wie immer: So ist es in der Praxis, der Standard garantiert nichts und du kannst dich nicht drauf verlassen. Und wenn man sich auf so etwas verlässt, ist einem wirklich nicht zu helfen

-
keinprofi schrieb:
inline ist keine zwingende Anweisung, sondern ein Ratschlag. Der Compiler muss sich nicht dran halten.
Das ist nicht richitg. Der Compiler versucht immer eine Inline-Expansion durchzuführen (wenn es sich lohnt ja, ansonsten nein), egal ob du inline schreibst oder nicht. Das Problem ist (inline schafft dazu dann Abhilfe), dass die Inline-Expansion nur dann durchgeführt werden kann, wenn sich Funktiondefinition und Aufrufstelle in derselben Übersetzungseinheit befinden. Falls dies nicht der Fall ist, kannst du inline benutzen, und ermöglichst somit dem Compiler, dass er die Funktion in einer entsprechenden Header definieren darf.
Siehe auch FAQ: http://www.c-plusplus.net/forum/105893
[EDIT] editiert nach davies Hinweis.
-
Gugelmoser schrieb:
Das ist nicht richitg. Der Compiler versucht immer eine Inline-Expansion durchzuführen (wenn es sich lohnt ja, ansonsten nein), egal ob du inline schreibst oder nicht.
Wo hab ich das behauptet?
inline-FAQ schrieb:
Da es ihm damit auch freigestellt ist, ob er einen Funktionsaufruf inline expandiert, kann es kein Sprachmittel geben, mit dem man dieses Verhalten erzwingen kann
keinprofi schrieb:
inline ist keine zwingende Anweisung, sondern ein Ratschlag. Der Compiler muss sich nicht dran halten.
-
keinprofi schrieb:
inline-FAQ schrieb:
Da es ihm damit auch freigestellt ist, ob er einen Funktionsaufruf inline expandiert, kann es kein Sprachmittel geben, mit dem man dieses Verhalten erzwingen kann
keinprofi schrieb:
inline ist keine zwingende Anweisung, sondern ein Ratschlag. Der Compiler muss sich nicht dran halten.
Ich glaube du verwechselst hier zwei paar Sachen:
Dem Compiler ist die Inline-Expansion freigestellt. Wenn es sich lohnt macht er es, wenn nicht dann nicht. Das Keyword inline hat nichts mit der Inline-Expansion zu tun.Inline-Expansion = Statt an die Adresse der Funktion zu springen, wird der Code der Funktion an der Aufrufstelle eingefügt.
Keyword inline = Hey Compiler, ich erlaube dir, dass du die Funktion in der entsprechenden Header definieren darfst, sodass du dann in der Lage bist, eventuell eine Inline-Expansion durchzuführen.
[EDIT] editiert nach davies Hinweis.
-
Man könnte fast meinen, du würdest glauben, dass folgender Code-Ausschnitt in Ordnung wäre:
//foo.cpp inline void f () { } void foo () { f(); } //bar.cpp inline void f (); void bar () { f(); }
-
außerdem ist auch ein reinterpret_cast hier nicht möglich. sizeof(void*) liefert nämlich nicht garantiert denselben wert wie sizeof(void(*)()). der "beste" weg (der einzige) ist es, den funktionszeiger in einen integralen typ zu konvertieren:
cout << hex << reinterpret_cast<long>(&fun) << endl;der compiler sollte dich dann zumindest warnen, falls long zu klein für den zeiger ist, und es ist erlaubt.
GCC ist zumindest mit dem teil richtig, der den zeiger auf die funktion in einen bool umwandelt, diese konvertierung ist nämlich explizit erlaubt.