warum der Typ von 'nil' nicht 'id' sondern 'void *' ist

8

In diesem Code

%Vor%

Ich habe diesen Fehler

  

Inkompatible Block-Zeigertypen, die 'id (^ __ strong) (void)' mit einem Ausdruck vom Typ 'void * (^) (void)'

initialisieren

Also muss ich nil explizit auf id type

setzen %Vor%

macht den Compiler glücklich. Warum kaufen nil ist nicht id type?

Und für diesen Code

%Vor%
  

Implizite Konvertierung des Objective-C-Zeigertyps 'NSObject *' in C-Zeigertyp 'typeof (((void *) 0))' (alias 'void *') erfordert eine überbrückte Umwandlung

Das heißt nil ist (void *)0 , aber ist nicht nur das gleiche wie NULL ? Ich denke, nil sollte (id)0 und Nil sollte (Class)0 sein?

Ich verwende Xcode 4.6.2

Compiler: Apple LLVM Version 4.2 (clang-425.0.28) (basierend auf LLVM 3.2svn)

    
Bryan Chen 15.06.2013, 10:40
quelle

3 Antworten

3

Sie verwenden einen abgeleiteten Rückgabetyp für Ihr Blockliteral, müssen dies aber nicht tun.

Der richtige Weg, um diesen Fehler zu entfernen, ist die Angabe eines Rückgabetyps für das Blockliteral:

%Vor%     
Adam Sharp 15.06.2013, 23:15
quelle
3

Wenn ein Block seinen Rückgabetyp weglässt, wird es jetzt die Aufgabe des Compilers, basierend auf den Rückgaben in seinem Rumpf den Typ des Blocks abzuleiten. Aber unglücklicherweise sucht CLANG nach den vollständig verfallenen Formen seiner zurückgegebenen Typen, was zu seltsamen Inkonsistenzen führt.

Das am besten zugängliche Beispiel ist das Sortieren eines Arrays. Der Typ des Vergleichsblocks ist NSComparisonResult(^)(id obj, id obj2) . Wenn Sie jedoch den Rückgabetyp NSComparisonResult auslassen, erhält der Compiler whiny:

%Vor%

Dieser Block zerfällt in einen Block vom Typ int(^)(id obj, id obj2) , den der Compiler als inkompatibel ansieht (wohl werden enums nur als ints bezeichnet, also sollte dies kompiliert werden).

Auf dieselbe Weise verfällt die ID in objc_object* , die immer weiter abfällt, bis sie void* erreicht, oder "irgendein generischer Zeiger" (gemäß der C-Sprachenspezifikation). void * und id sind ganz sicher nicht vom selben Typ. Um dies zu umgehen, müssen Sie dem Compiler versprechen, dass der zurückgegebene Typ wirklich das ist, was er ist, und der einzige Weg dazu besteht in der Umwandlung.

LLVM 5.0 behebt das, indem es die Inferenzen des Compilers viel intelligenter macht.

    
CodaFi 15.06.2013 19:59
quelle
0

Ich weiß nicht, warum nil ist #define nil NULL in der Apple-Header (das ist eine Tatsache, aber ich weiß nicht den Grund, warum es nicht (id)0 wie man erwarten würde), aber ich hatte nie den Fehler, den Sie sind Erwähnung in der neuesten Version von Xcode und dem Compiler.

Ich glaube, ich erinnere mich an einen Fehler in früheren Versionen des Legacy-Compilers, der implizite Umwandlungen wie diese in Blöcke von Rückgabetypen und allem falsch interpretierte.

Welchen Compiler benutzen Sie? LLVM-GCC 4.2? oder Apple LLVM 4.2? Ein älterer Compiler? Überprüfen Sie die Build-Einstellungen Ihres Projekts. Ich empfehle, zu Apple LLVM zu wechseln und zu überprüfen, ob das Ihr Problem löst .

(Tatsächlich wird LLVM-GCC nur für den Übergang vom alten GCC zum neuen LLVM seit einigen Versionen von Xcode verwendet, ist aber veraltet und soll in der nächsten Version von Xcode entfernt werden )

    
AliSoftware 15.06.2013 11:14
quelle