Frage

Was ist der Unterschied zwischen einer statischen Member-Funktion und einem extern „C“ Verknüpfung Funktion? Wenn zum Beispiel „makecontext“ in C ++ verwendet wird, muss ich einen Zeiger zu übergeben funktionieren. Google empfiehlt es extern „C“ Verknüpfung zu verwenden, da „makecontext“ C. Aber ich fand heraus, dass die Verwendung als auch statische Arbeiten. Bin ich einfach nur Glück oder ...

class X {
   public:
   static void proxy(int i) {}
}
makecontext(..., (void (*)(void)) X::proxy, ...);

vs

extern "C" void proxy(int i) {}
makecontext(..., (void (*)(void)) proxy, ...);

EDIT: Können Sie einen Compiler oder Architektur zeigen, wo die statische Elementversion nicht funktioniert (und es ist kein Bug im Compiler)

War es hilfreich?

Lösung

Ja, Sie haben einfach Glück :) Das extern „C“ ist eine Sprache Verknüpfung für die C-Sprache, die jeder C ++ Compiler unterstützt hat, neben extern „C ++“, das ist die Standardeinstellung. Compiler können andere Sprachbindungen unterstützt. GCC zum Beispiel unterstützt extern „Java“, die mit Java-Code Schnittstelle ermöglicht (obwohl das recht umständlich ist).

extern "C" weist den Compiler an, die Ihre Funktion von C-Code aufrufbar ist. Das kann, aber nicht muss, gehören die entsprechende Aufrufkonvention und das entsprechenden Namen Mangeln C-Sprache (manchmal auch als „Dekoration“) unter anderem abhängig von der Implementierung. Wenn Sie eine statische Memberfunktion haben, denn es ist die Aufrufkonvention ist das eine Ihrer C ++ Compiler. Oft sind sie die gleichen wie für den C-Compiler von dieser Plattform - so sagte ich einfach Glück haben. Wenn Sie einen C-API haben und Sie einen Funktionszeiger übergeben, besser gesagt immer eine auf eine Funktion, mit extern „C“ deklarierte wie

extern "C" void foo() { ... }

Auch wenn die Funktion Zeigertyp enthält nicht die Verknüpfungsvorschrift, sondern sieht aus wie

void(*)(void)

Die Verknüpfung ein integraler Bestandteil der Art ist - man kann es einfach nicht ausdrücken direkt ohne typedef:

extern "C" typedef void(*extern_c_funptr_t)();

Der Comeau C ++ Compiler, im Strict-Modus, wird einen Fehler zum Beispiel emittiert, wenn Sie versuchen, die Adresse der extern „C“ Funktion von oben auf einen (void(*)()) zuweisen, beause dies ein Zeiger auf eine Funktion mit C ++ Verknüpfung ist.

Andere Tipps

Beachten Sie, dass extern C ist die empfohlen Art und Weise von C / C ++ Interoperabilität. Hier ist der Meister darüber zu reden. Hinzufügen zu eduffy Antwort: beachten Sie, dass statische Funktionen und Variablen im globalen Namespace sind veraltet. Verwenden Sie einen anonymen Namespace mindestens.

Zurück zur extern C: Wenn Sie nicht über extern C verwenden die genauen verstümmelten Namen kennen und es zu verwenden. Das ist viel mehr Schmerz.

extern "C" deaktiviert den C ++ Compiler den Namen Mangeln (die Überlastung erforderlich).

Wenn Sie eine Funktion in A.cpp erklären static werden, dann kann es nicht durch B.cpp gefunden werden (es ist Überbleibsel aus C, und es hat die gleiche Wirkung eine Funktion innerhalb eines anonymen Namespace setzen).

Die meisten von dem, was extern "C" tut, ist weitgehend Compiler abhängig. Viele Plattformen ändern Sie den Namen Mangeln und Konvention vor der Erklärung basiert nennen, aber nichts davon wird durch den Standard festgelegt. Wirklich das einzige, was verlangt der Standard ist, dass der Code im Block von C-Funktionen aufrufbar ist. Was Ihre konkrete Frage, sagt der Standard:

  

Zwei Funktionstypen mit unterschiedlichen   Sprachbindungen sind unterschiedliche Typen   auch wenn sie ansonsten identisch sind.

Das bedeutet extern "C" void proxy(int i) {} und /*extern "C++"*/void proxy(int i) {} haben verschiedene Arten, und als Ergebnis Zeiger auf diese Funktionen würden verschiedene Arten als auch. Der Compiler nicht Ihren Code aus dem gleichen Grunde scheitert es nicht ein großes Stück Arbeit scheitern würde wie:

int *foo = (int*)50;
makecontext(..., (void (*)(void)) foo, ...);

Dieser Code kann auf einige Plattform arbeiten, aber das bedeutet nicht, es auf einer anderen Plattform funktioniert (auch, wenn der Compiler vollständig standardkonform war). Sie nutzen die Vorteile, wie die jeweilige Plattform arbeitet, die in Ordnung sein könnte, wenn Sie nicht besorgt über portable Code zu schreiben.

Wie für statische Member-Funktionen, sie sind nicht erforderlich, um einen this Zeiger haben, so dass der Compiler frei ist, sie als nicht-Memberfunktion zu behandeln. Auch hier ist das Verhalten plattformspezifisch.

Generell

Speicherklassen:

Speicherklassen werden verwendet, um die Dauer und den Umfang einer Variablen oder Kennung angeben.

Dauer:

Dauer gibt die Lebensdauer einer Variablen.

Gültigkeitsbereich:

Scope gibt die Sichtbarkeit der Variablen.

Statische Speicherklasse:

Die statische Speicherklasse wird verwendet, um eine Kennung zu deklarieren, die eine lokale Variable ist entweder auf eine Funktion oder eine Datei und das existiert und behält seinen Wert nach geht die Steuerung von dem sie deklariert wurde. Diese Speicherklasse hat eine Dauer, die dauerhaft ist. Eine Variable dieser Klasse deklariert behält seinen Wert von einem Aufruf der Funktion zum nächsten. Der Umfang ist lokal. Eine Variable ist bekannt, nur durch die Funktion innerhalb oder erklärt deklariert wird, wenn global in einer Datei ist es bekannt, oder nur in dieser Datei durch die Funktionen zu sehen. Diese Speicherklasse garantiert, dass Deklaration der Variablen initialisiert auch die Variable auf Null oder alle Bits aus.

Externe Speicherklasse:

Die externe Speicherklasse wird verwendet, um eine globale Variable zu deklarieren, die in einem Programm alle Funktionen sind bekannt in einer Datei und in der Lage zu den Funktionen bekannt werden. Diese Speicherklasse hat eine Dauer, die dauerhaft ist. Jede Variable dieser Klasse behält seinen Wert, bis sie durch eine andere Zuordnung geändert. Der Umfang ist global. Eine Variable kann von allen Funktionen innerhalb eines Programms bekannt oder gesehen werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top