Anonyme Funktionen, die GCC-Anweisungsausdrücke verwenden
Diese Frage ist nicht besonders spezifisch, es ist wirklich für meine eigene C-Anreicherung und ich hoffe, andere finden es nützlich.
Disclaimer: ich weiß, viele werden den Impuls haben, zu reagieren: "wenn Sie versuchen zu tun, FP dann verwenden Sie einfach eine funktionale Sprache". Ich arbeite in einer embedded-Umgebung, muss der link auf viele andere C-Bibliotheken, und nicht viel Raum für viele weitere große shared libs und keine Unterstützung für viele Sprachen-Laufzeiten. Darüber hinaus dynamische Speicherverwaltung in Frage. Ich bin auch nur wirklich neugierig.
Viele von uns haben gesehen, diese nette C-makro für lambda-Ausdrücke:
#define lambda(return_type, function_body) \
({ \
return_type __fn__ function_body \
__fn__; \
})
Und ein Beispiel für die Verwendung ist:
int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });
max(4, 5); //Example
Mit gcc -std=c89 -E test.c
lambda erweitert:
int (*max)(int, int) = ({ int __fn__ (int x, int y) { return x > y ? x : y; } __fn__; });
So, das sind meine Fragen:
- Was genau macht die Zeile int (*X); erklären? Natürlich int * X; ist ein Zeiger auf ein integer, aber wie diese zwei sich unterscheiden?
- Sich ein Blick auf die exapnded makro, was auf der Erde ist der Letzte
__fn__
tun? Wenn ich einen test schreiben Funktionvoid test() { printf("hello"); } test;
-, dass sofort ein Fehler ausgegeben. Ich verstehe nicht, dass syntax. - Was bedeutet das für die Fehlersuche? (Ich bin Planung zu Experimentieren, mich mit diesem und gdb, aber andere Erfahrungen oder Meinungen wären toll). Würde diese Schraube statische Analysatoren?
InformationsquelleAutor der Frage B. VB. | 2012-05-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese Erklärung (block scope):
ist nicht C, sondern gilt GNU C.
Es macht Gebrauch von zwei
gcc
Erweiterungen:Beide verschachtelte Funktionen (Definition einer Funktion innerhalb einer compound-Anweisung) und Aussage Ausdrücken (
({})
im Grunde ein block, ergibt sich ein Wert) sind nicht zulässig in C und kommt aus der GNU C.In einer Erklärung Ausdruck, der Letzte Ausdruck ist der Wert des Konstrukts. Dies ist der Grund, warum die verschachtelte Funktion
__fn__
erscheint als ein Ausdruck am Ende der Anweisung Ausdruck. Eine Funktion Kennung (__fn__
im letzten Ausdruck) in einen Ausdruck umgewandelt wird, um einen Zeiger auf eine Funktion, die von den üblichen Umbauten. Dies ist der Wert, der verwendet wird zum initialisieren der Funktion Zeigermax
.InformationsquelleAutor der Antwort ouah
Ihre lambda-makro nutzt zwei funky features. Zuerst wird es verwendet, verschachtelte Funktionen, um tatsächlich definieren den Körper Ihrer Funktion (also deine lambda ist nicht wirklich anonym, es wird eine implizite
__fn__
variable (die sollte umbenannt werden, um etwas anderes, als Doppel-leading-underscore Namen sind reserviert für den compiler, also vielleicht so etwas wieyourapp__fn__
wäre besser).All dies wird selbst durchgeführt, die in einem GCC-compound-Anweisung (siehe http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs), die grundlegende format, von denen geht so etwas wie:
die Letzte Anweisung des compound-Anweisung wird die Adresse des gerade erklärten Funktion. Jetzt
int (*max)(int,int)
einfach zugewiesen bekommt, den Wert der compound-Anweisung, die jetzt der Zeiger auf den "anonym" - Funktion einfach erklärt.Debuggen von Makros sind eine königliche Schmerz natürlich.
Als für der Grund, warum
test;
.. zumindest hier habe ich das "test erneut deklariert als andere Art von symbol', was ich davon ausgehen, bedeutet GCC ist die Behandlung von es als eine Erklärung und nicht nur ein (nutzloses) Ausdruck. Weil untypisierte Variablen standardmäßigint
und weil Sie schon erklärt habentest
als eine Funktion (im wesentlichenvoid (*)(void)
) erhalten Sie.. aber ich könnte falsch sein darüber.Dies ist nicht tragbar von einer Strecke der Phantasie, aber.
InformationsquelleAutor der Antwort Mark Nunberg
int (*max)(int, int)
ist der Typ der variable, die Sie deklarieren. Es ist definiert als ein Funktionszeiger namens max, die gibt int und übernimmt zwei int-Werte als Parameter.__fn__
bezieht sich auf den Namen der Funktion, in diesem Fall ist max.Ich habe darauf keine Antwort gibt. Ich könnte mir vorstellen, Sie können Schritt für Schritt durch, wenn Sie haben, führen Sie es durch den Präprozessor.
InformationsquelleAutor der Antwort gcochard
Teilweise beantworten:
Es ist nicht int(*X) Sie interessiert sind. Es ist int (*X)(y,z). Das ist ein Funktionszeiger auf die Funktion, die aufgerufen wird X (y,z) und gibt die int.
Für das debugging, das wird echt schwer. Die meisten Debugger können nicht verfolgen, über ein makro. Sie würden wahrscheinlich haben, um das Debuggen der Montage.
InformationsquelleAutor der Antwort Steve Rowe