Ich arbeite mit einer blockbasierten API und stolperte über ein Szenario, in dem ich einen Blockparameter übergab, der eine Signatur hatte, die nicht mit dem typedef-Parameter übereinstimmte, den die Methode erwartet hatte. Zu meiner Überraschung schien sich der Compiler nicht darum zu kümmern und die App stürzte nicht ab. Ist das erwartetes Verhalten? Beispiel:
%Vor%Angabe einer leeren Argumentspezifikation wie in
%Vor%bedeutet "nicht spezifizierte" Argumente. Die beiden Typen sind also wie geschrieben kompatibel. Ändern der ersten Deklaration in
%Vor%gibt an, dass der Block keine Argumente annimmt und Sie einen Fehler erhalten.
K & amp; R C spezifiziert, dass eine leere Argumentliste "nicht spezifiziert" bedeutet. Die C-Block-Spezifikation besagt, dass dies für Blocktyp-Deklarationen nicht wahr ist (vgl. Ссылка ) aber : Sowohl GCC als auch Clang implementieren das K & amp; R-Verhalten als Spracherweiterung.
Aus der Clang Blocks-Spezifikation:
Variadic
...
Argumente werden unterstützt. [variadic.c] Ein Block, der keine Argumente annimmt, muss void in der Argumentliste angeben [voidarg.c]. Eine leere Parameterliste repräsentiert nicht, wie K & amp; R, eine nicht spezifizierte Argumentliste. Hinweis: Sowohl gcc als auch clang unterstützen den K & R-Stil als Komfort.
Grundsätzlich ist dies eine uralte Eigenart der C-Syntax. In alten Zeiten war die Deklarationssyntax der C-Funktion ziemlich unterschiedlich, und leere Klammern deuteten darauf hin, dass der Funktion eine beliebige Anzahl von Argumenten übergeben werden konnte. Aus Gründen der Abwärtskompatibilität haben Compiler im Allgemeinen die alte Deklarationssyntax für Funktionsanweisungen zugelassen. Und aus irgendeinem Grund hat Apple beschlossen, diese Syntax im Blockstandard gleichzeitig abzulehnen, während sie es tatsächlich erlaubt, mit Blöcken sowohl in GCC als auch in Clang verwendet zu werden.
Kurz gesagt: Um zu erklären, dass ein Block keine Argumente benötigt, müssen Sie ihn explizit als void(^MyBlock)(void)
Das ist eine C-Sache. Ein Funktions- oder Blockprototyp mit einer leeren Argumentliste bedeutet, dass "die Funktion (oder der Block) beliebige Argumente akzeptiert". Wenn Sie angeben möchten, dass der Block keine Argumente haben soll, müssen Sie dies explizit so sagen:
%Vor%Dies ist weitgehend historisch von den Tagen vor ANSI, als es keine Funktionsprototypen gab und alle Funktionsdeklarationen (im Gegensatz zu Definitionen) wie folgt aussahen:
%Vor%Tags und Links objective-c objective-c-blocks