Warum sind verschachtelte Funktionen nicht unterstützt durch den C-standard?
Es scheint nicht, wie es wäre zu schwer zu implementieren in der Montage.
gcc hat auch ein flag (-fnested-Funktionen) zu ermöglichen Ihre Verwendung.
- Es gibt einen Unterschied zwischen dem, was würde/würde nicht "zu schwer" umzusetzen, und welche die standards-Definition von Körper wählte einschließen oder weglassen von der Norm. GCC-Unterstützung für das bedeutet nur, dass es etwas ist, was umgesetzt wird, die außerhalb des Anwendungsbereichs der Norm - nämlich, es ist eine nicht-standard-Funktion. GCC ist nur eine Implementierung eines Compilers, der sich auf die C-standard; es ist in keiner Weise eingeschränkt, nur bieten, was in den standard.
- klingt wie eine Antwort, eher als ein Kommentar
- Matt Ball: Meine Frage ist ja, warum die standards definieren Körper wählte weglassen, eine solche Funktion. Mein Verweis auf gcc war eher ein Beispiel für "es kann so geschehen, warum ist es nicht".
- Verwandte: stackoverflow.com/questions/666586/...
- kann getan werden, also warum nicht tun Sie es" ist, wie Sie am Ende mit Sprachen wie C++. Ob das eine gute oder eine schlechte Sache ist bis zu Ihnen. (und ja, C++ nicht direkt unterstützt, verschachtelte Funktionen, aber Sie können immer eine lokale Funktor).
- Ich wäre nicht zufrieden gewesen, wenn jemand geschrieben, dass die Antwort gab es auf meine Frage. Es ist weitgehend eine nicht-Antwort, daher postest es in einem Kommentar. Dies ist immer ein bisschen meta-nun, vielleicht werden diese Kommentare verschoben werden sollen... 😛
- "Meine Frage ist ja, warum die standards definieren Körper entschied sich das auslassen solch ein feature" - Das ist keine gültige Frage ALSO.
- Es wurde nicht geschlossen, es ist also vertretbar, dass es ist eine gültige Frage ALSO.
- jinawee Kommentar ist völlig irrelevant.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es stellt sich heraus, dass Sie gar nicht so einfach zu implementieren ist richtig.
Sollte eine interne Funktion haben, den Zugang zu den enthaltenden Bereich der Variablen?
Wenn nicht, gibt es keinen Punkt in Schachteln, nur machen es die statische (zur Grenze der Sichtbarkeit, um die übersetzungseinheit es ist in) und fügen Sie einen Kommentar zu sagen "Dies ist eine Hilfsfunktion, die nur von myfunc()".
Wenn Sie möchten, den Zugang zu den mit scope-Variablen, obwohl Sie im Grunde zwingen, es zu erzeugen-Verschlüsse (die alternative ist das einschränken, was Sie tun können, mit verschachtelten Funktionen genug, um Sie unbrauchbar).
Ich denke, dass GCC tatsächlich behandelt diese durch erzeugen (zur Laufzeit) eine eindeutige thunk für jeden Aufruf der, die Funktion, gibt es ein Kontext-Zeiger und ruft dann die verschachtelte Funktion. Dies endet als ein ziemlich Eklig zu hacken, und etwas, dass einige durchaus vernünftige Implementierungen kann das nicht tun (zum Beispiel auf ein system, das verbietet die Ausführung von beschreibbaren Speicher, die eine Menge von modernen Betriebssystemen zu tun aus Gründen der Sicherheit).
Der einzige vernünftige Weg, um es Arbeit im Allgemeinen ist die Kraft aller Funktionszeiger zu tragen, um eine versteckte Kontext-argument, und alle Funktionen, die es zu akzeptieren (da im Allgemeinen Fall Sie nicht wissen, Wann Sie es nennen, ob es eine Schließung oder eine nicht geschlossene Funktion). Dies ist unangemessen zu verlangen, die in C sowohl technische als auch kulturelle Gründe, so wir stecken mit der option, entweder mit expliziten Kontext Zeiger auf fake-Verschluss statt verschachteln von Funktionen, oder mit einem höheren level-Sprache, die Infrastruktur, die benötigt wird um es richtig zu machen.
Möchte ich Zitat etwas vom BDFL (Guido van Rossum):
Hervorhebung ist von mir.
Ich glaube, er bezog sich auf verschachtelte Rahmen in Python (und als David weist in den Kommentaren, das war 1993, und Python unterstützt voll geschachtelte Funktionen jetzt) - aber ich denke, dass die Aussage immer noch gilt.
Den anderen Teil könnte es gewesen Verschlüsse.
Wenn Sie eine Funktion wie diese C-ähnlichen code:
Wenn Sie
bar
einen Rückruf von einer Art, was passiert mit x? Dies ist gut definiert, mit vielen neuen, höheren Sprachen, aber AFAIK gibt es keine gut definierten Weise zu verfolgen, dassx
im C-tutbar
Gegenzug 6 jedes mal, oder muss aufeinander folgende Aufrufe vonbar
Gegenzug erhöht Werte? Das könnte möglicherweise eine ganze neue Ebene der Komplexität zu C relativ einfache definition.bar
zurückkehren würde, 5,6,7,... Verschachtelte Funktionen fast erfordern - Funktionen (first-order-Werte.Sehen C FAQ 20.24 und das GCC Handbuch für mögliche Probleme:
Dies ist nicht wirklich schwerer als einige andere problematische Teile des C-standard, also ich würde sagen, die Gründe sind zumeist historische (C99 ist nicht wirklich , dass unterscheidet sich von K&R-C feature-Weise).
Gibt es einige Fälle, in denen verschachtelte Funktionen mit lexikalischen Bereich könnte sinnvoll sein, (berücksichtigen Sie, dass eine rekursive innere Funktion, die nicht mehr stack-Speicher für die Variablen, die in den äußeren Umfang, ohne die Notwendigkeit für eine statische variable), aber ich hoffe Sie können darauf Vertrauen, dass der compiler richtig inline-Funktionen, dh eine Lösung mit einer separaten Funktion wird nur Ausführlicher.
Verschachtelte Funktionen sind eine sehr heikle Sache. Sie machen diese Verschlüsse? Wenn nicht, dann haben Sie keinen Vorteil zu normalen Funktionen, da Sie keinen Zugriff auf die lokalen Variablen. Wenn Sie es tun, dann was tun Sie, um stack-allokierten Variablen? Sie haben, um Sie irgendwo anders, so dass, wenn Sie rufen Sie die verschachtelte Funktion später, die variable ist immer noch da. Dies bedeutet, Sie nehme den Speicher, so haben Sie zu reservieren Zimmer für Sie auf dem heap. Ohne GC, das bedeutet, dass der Programmierer ist jetzt zuständig für die Reinigung der Funktionen. Etc... in C# wird dies, aber Sie haben einen GC, und es ist eine deutlich neuere Sprache als C
Es wäre auch nicht allzu schwer sein, Mitglieder hinzufügen von Funktionen zu Strukturen, aber Sie sind nicht in der standard entweder.
Features werden nicht Hinzugefügt, um die C-standard basiert auf allein, ob oder nicht Sie sind einfach zu implementieren. Es ist eine Kombination von vielen anderen Faktoren, wie z.B. der Zeitpunkt, in dem der standard geschrieben wurde, und was war üblich /praktisch dann.
ANSI C wurde für 20 Jahre. Vielleicht zwischen 1983 und 1989 kann der Ausschuss besprochen haben, es im Licht des Status der compiler-Technologie zu der Zeit, aber wenn Sie es Taten, Ihre Argumentation ist verloren in der dunklen und entfernten Vergangenheit.
Einen weiteren Grund: es ist überhaupt nicht klar, dass verschachtelte Funktionen sind wertvoll. Zwanzig-ungerade Jahren habe ich umfangreiche Programmierung und Wartung (VAX) Pascal. Wir hatten viel alten code, der aus der starken Nutzung von verschachtelten Funktionen. Auf den ersten, ich dachte, das war so cool (im Vergleich zu K&R-C, die ich gearbeitet hatte, bevor) und begann, es selbst zu tun. Nach einer Weile beschloss ich, es war eine Katastrophe, und blieb stehen.
War das problem, dass eine Funktion haben könnte große viele Variablen im scope -, zähl-Variablen für alle Funktionen in dem es verschachtelt ist. (Einige alte code hatte zehn Ebenen verschachteln; fünf war durchaus üblich, und bis ich meine Meinung geändert, ich codiert einige die letztere selbst.) Variablen in der nesting-Stapel können den gleichen Namen haben, so dass die "innere" Funktion lokale Variablen konnte mask-Variablen mit dem gleichen Namen in die "äußere" Funktionen. Eine lokale variable von einer Funktion, die in C-artigen Sprachen ist ganz privat für Sie, könnte geändert werden, durch einen Aufruf an eine verschachtelte Funktion. Die Menge der möglichen Kombinationen dieser jazz war in der Nähe von unendlich, und ein Alptraum zu verstehen beim Lesen von code.
So, ich nenne diese programmierungskonstrukt "semi-Globale Variablen" anstelle von "verschachtelte Funktionen", und erzählen anderen Menschen, die sich auf den code, das einzige was schlimmer ist als eine Globale variable wurde eine semi-Globale variable, und bitte nicht erstellen. Ich würde verboten haben es aus der Sprache, wenn ich könnte. Leider gab es keine solche option für den compiler...
Ich Stimme mit Dave Vandervies.
Definition einer geschachtelten Funktion ist viel besser, coding style als die Definition im globalen Bereich, wodurch statische und hinzufügen eines Kommentars sagen: "Dies ist eine Hilfsfunktion, die nur von myfunc()".
Was ist, wenn Sie benötigt eine Hilfsfunktion für diese helper-Funktion? Möchten Sie einen Kommentar hinzufügen, "Dies ist eine helper-Funktion für die erste Hilfsfunktion verwendet, die nur von myfunc"? Woher nehmen Sie die Namen aus benötigt für alle Funktionen, ohne das verschmutzen der namespace komplett?
Wie verwirrend kann code geschrieben werden?
Aber natürlich gibt es das problem mit dem Umgang mit closuring, d.h. die Rückgabe einen Zeiger auf eine Funktion, die den Zugriff auf Variablen in der Funktion definiert, von dem es zurückgegeben wird.
Entweder Sie nicht zulassen, dass Referenzen auf lokale Variablen der enthaltenden Funktion in der enthalten ist, und die Verschachtelung ist nur eine scoping-feature, ohne viel zu verwenden, oder Sie tun. Wenn Sie es tun, ist es nicht eine so einfache Funktion: Sie werden in der Lage, um eine verschachtelte Funktion aus einer anderen, während der Zugriff auf die richtigen Daten, und Sie haben auch zu berücksichtigen, rekursive Aufrufe. Das ist nicht unmöglich-Techniken sind gut bekannt und wo gut zu beherrschen, als C entwickelt wurde (Algol 60 hatte bereits die Funktion). Aber es erschwert die run-time-Organisation und der compiler und verhindern, dass ein einfaches mapping assembly-Sprache (eine Funktion, die Zeiger tragen muss auf Informationen über das, gut gibt es alternativen, wie die gcc verwenden). Es war der Rahmen für die Umsetzung der Sprache C entwickelt wurde, um zu sein.