Gibt es überhaupt eine Möglichkeit, das [NSString stringWithFormat:@"%p", myVar]
von Objective-C in der neuen Swift-Sprache zu simulieren ?
Beispielsweise:
let str = "A String"
println(" str value \(str) has address: ?")
swift
debugging
memory-address
Apouche
quelle
quelle
[NSString stringWithFormat:@"%p", myVar]
,myVar
muss ein Zeiger sein. Ist in Ihrem Swift-Codestr
kein Zeiger. Der Vergleich trifft also nicht zu.Antworten:
Swift 2
Dies ist jetzt Teil der Standardbibliothek :
unsafeAddressOf
.Swift 3
Verwenden Sie für Swift 3
withUnsafePointer
:quelle
withUnsafePointer
führt zu einemcannot pass immutable value as inout argument
Fehler.print(self.description)
Drucke<MyViewController: 0x101c1d580>
, wir verwenden es als Referenz.var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }
druckt0x16fde4028
die deutlich andere Adresse. Kann jemand erklären warum?0x101c1d580
print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
UnsafePointer
ist eine Struktur. Um also die Adresse zu drucken, auf die sie zeigt (und nicht die Struktur selbst), müssen Sie druckenString(format: "%p", $0.pointee)
!Hinweis: Dies gilt für Referenztypen.
Swift 4/5:
Druckt die Speicheradresse von someVar. (danke an @Ying)
Swift 3.1:
Druckt die Speicheradresse von someVar.
quelle
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
kann folgendermaßen erfolgen :print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
.Unmanaged.passUnretained(someVar).toOpaque()
(keine generische Spezifikation erforderlich)debugDescription
sie am Ende hinzuzufügen .Beachten Sie, dass diese Antwort ziemlich alt war. Viele der beschriebenen Methoden funktionieren nicht mehr. Speziell
.core
kann nicht mehr zugegriffen werden.Die Antwort von @ draw ist jedoch richtig und einfach:
Die Antwort auf Ihre Fragen lautet also:
Hier ist die ursprüngliche Antwort, die als richtig markiert wurde (für Nachwelt / Höflichkeit):
Schnelle "versteckt" Zeiger, aber sie existieren immer noch unter der Haube. (weil die Laufzeit es braucht und aus Kompatibilitätsgründen mit Objc und C)
Es gibt jedoch einige Dinge zu wissen, aber zuerst, wie man die Speicheradresse eines Swift-Strings druckt?
Dadurch wird die Speicheradresse der Zeichenfolge gedruckt. Wenn Sie XCode -> Debug-Workflow -> Speicher anzeigen öffnen und zur gedruckten Adresse wechseln, werden die Rohdaten der Zeichenfolge angezeigt. Da dies ein String-Literal ist, ist dies eine Speicheradresse im Speicher der Binärdatei (nicht Stapel oder Heap).
Wenn Sie dies jedoch tun
Dies befindet sich auf dem Stapel, da die Zeichenfolge zur Laufzeit erstellt wird
HINWEIS: .core._baseAddress ist nicht dokumentiert. Ich habe festgestellt, dass es im Variableninspektor angezeigt wird und möglicherweise in Zukunft ausgeblendet wird
_baseAddress ist nicht für alle Typen verfügbar, hier ein weiteres Beispiel mit einem CInt
Wo
takesInt
ist eine C-Helferfunktion wie diese?Auf der Swift-Seite ist diese Funktion so
takesInt(intptr: CMutablePointer<CInt>)
, dass ein CMutablePointer zu einem CInt führt und Sie ihn mit & varname erhalten könnenDie Funktion wird gedruckt
0x7fff5fbfed98
, und an dieser Speicheradresse finden Sie 289 (in hexadezimaler Schreibweise). Sie können den Inhalt mit ändern*intptr = 123456
Nun noch ein paar andere Dinge zu wissen.
String ist schnell ein primitiver Typ, kein Objekt.
CInt ist ein Swift-Typ, der dem C int-Typ zugeordnet ist.
Wenn Sie die Speicheradresse eines Objekts möchten, müssen Sie etwas anderes tun.
Swift verfügt über einige Zeigertypen, die bei der Interaktion mit C verwendet werden können. Weitere Informationen hierzu finden Sie hier: Swift-Zeigertypen
Darüber hinaus erfahren Sie mehr darüber, wie sie ihre Deklaration untersuchen (cmd + Klicken Sie auf den Typ), um zu verstehen, wie sie konvertiert werden eine Art Zeiger in eine andere
printptr
ist eine C-Hilfsfunktion, die ich mit dieser Implementierung erstellt habeWieder ein Beispiel für die gedruckte Adresse:
0x6000000530b0
und wenn Sie den Speicherinspektor durchlaufen, finden Sie Ihren NSStringEine Sache, die Sie mit Zeigern in Swift machen können (dies kann sogar mit inout-Parametern gemacht werden)
Oder mit Objc / c interagieren
quelle
Um die (Heap-) Adresse eines Objekts abzurufen
( Bearbeiten: Swift 1.2 enthält jetzt eine ähnliche Funktion namens
unsafeAddressOf
.)In Objective-C wäre dies
[NSString stringWithFormat:@"%p", o]
.o
ist ein Verweis auf die Instanz. Wenno
also eine andere Variable zugewiesen isto2
, ist die zurückgegebene Adresse füro2
dieselbe.Dies gilt nicht für Strukturen (einschließlich
String
) und primitive Typen (wieInt
), da diese direkt auf dem Stapel leben. Wir können jedoch den Speicherort auf dem Stapel abrufen.Um die (Stapel-) Adresse einer Struktur, eines eingebauten Typs oder einer Objektreferenz abzurufen
In Objective-C wäre dies
[NSString stringWithFormat:@"%p", &o]
oder[NSString stringWithFormat:@"%p", &i]
.s
ist struct. Wenns
also eine andere Variable zugewiesen wirds2
, wird der Wert kopiert und die zurückgegebene Adresse fürs2
ist unterschiedlich.Wie es zusammenpasst (Zeigerrückblick)
Wie in Objective-C sind zwei verschiedene Adressen zugeordnet
o
. Der erste ist der Ort des Objekts, der zweite ist der Ort der Referenz (oder des Zeigers) auf das Objekt.Ja, dies bedeutet, dass der Inhalt der Adresse 0x7fff5fbfe658 die Nummer 0x6100000011d0 ist, wie der Debugger uns mitteilen kann:
Abgesehen davon, dass Strings Strukturen sind, funktioniert dies intern ziemlich genau so wie in (Objective-) C.
(Stand Xcode 6.3)
quelle
TL; DR
( Kern )
In Swift beschäftigen wir uns entweder mit Werttypen (Strukturen) oder Referenztypen (Klassen). Wenn Sie:
An der Adresse X wird etwas Speicher zugewiesen, und an dieser Adresse finden wir den Wert 42. Wenn Sie dies tun,
&n
wird ein Zeiger erstellt, der auf die Adresse X zeigt, und es&n
wird uns mitgeteilt, won
sich dieser befindet.Wenn Sie:
Der Speicher wird an zwei Stellen zugewiesen:
Wie gesagt, Klassen sind Referenztypen: Der Wert von
c
befindet sich also an der Adresse X, an der wir den Wert von Y finden. Und an der Adresse Y + 16 finden wirfoo
und an der Adresse Y + 24 finden wirbar
( Bei + 0 und + 8 finden wir Typdaten und Referenzzählungen. Mehr kann ich dazu nicht sagen ...).0x2a
ist 42 (foo) und0x54
ist 84 (bar).In beiden Fällen mit
&n
oder&c
wir geben uns die Adresse X. Für Werttypen ist dies das, was wir wollen, aber nicht für Referenztypen.Wenn Sie:
Wir erstellen einen Zeiger auf die Referenz, dh einen Zeiger, der auf die Adresse X zeigt. Dasselbe gilt bei der Verwendung
withUnsafePointer(&c) {}
.Jetzt, da wir besser verstehen, was unter der Haube vor sich geht, und jetzt, wo wir unter Adresse X die Adresse Y finden (die wir wollen), können wir Folgendes tun, um sie zu erhalten:
Überprüfen:
Es gibt andere Möglichkeiten, dies zu tun:
toOpaque()
ruft tatsächlich anunsafeBitCast(c, to: UnsafeMutableRawPointer.self)
.Ich hoffe das hat geholfen ... es hat mir geholfen 😆.
quelle
MemoryLocation
2 verschiedene Adressen erzeugt werden.Referenztypen:
===
Der Identitätsoperator wird verwendet, um zu überprüfen, ob 2 Objekte auf dieselbe Referenz verweisen.ObjectIdentifier
diese Option , um die Speicheradresse abzurufenCode:
Werttypen:
quelle
Verwenden Sie einfach dies:
quelle
MyClass?
" nicht mit CVarArg übereinstimmt, können Sie dies tunextension Optional : CVarArg { }
. Andernfalls scheint dies Adressen zu drucken, ohne den "unsicheren" Wahnsinn der anderen Antworten.var _cVarArgEncoding: [Int]
onCVarArg
. Nicht klar, wie das umgesetzt werden soll.Wenn Sie dies nur im Debugger sehen und nichts anderes damit tun möchten, müssen Sie den
Int
Zeiger nicht tatsächlich abrufen. Verwenden Sie Folgendes, um die Zeichenfolgendarstellung der Adresse eines Objekts im Speicher abzurufen:Anwendungsbeispiel:
Denken Sie außerdem daran, dass Sie ein Objekt einfach drucken können, ohne es zu überschreiben
description
, und dass seine Zeigeradresse neben aussagekräftigerem (wenn auch häufig kryptischem) Text angezeigt wird.quelle
Swift 5
Verwendung:
quelle
Unmanaged.passUnretained(myObject).toOpaque()
funktioniert stattdessen richtig.AnyObject
Parameter. Ich würdeAny
als Eingabetyp bevorzugen .In Swift4 über Array:
quelle
self?.array
.Die anderen Antworten sind in Ordnung, obwohl ich nach einer Möglichkeit gesucht habe, die Zeigeradresse als Ganzzahl zu erhalten:
Nur ein kleines Follow-up.
quelle
Die Antwort @Drew kann nur für den Klassentyp verwendet werden.
Die Antwort @nschum kann nur für den Strukturtyp sein.
Wenn Sie jedoch die zweite Methode verwenden, um die Adresse eines Arrays mit dem Werttypelement abzurufen. Swift kopiert das gesamte Array, da das Swift-Array beim Schreiben kopiert wird und Swift nicht sicherstellen kann, dass es sich so verhält, wenn es die Kontrolle an C / C ++ übergibt (was durch Abrufen
&
der Adresse ausgelöst wird ). Und wenn Sie stattdessen die erste Methode verwenden, wird diese automatisch konvertiertArray
,NSArray
was wir sicherlich nicht wollen.Der einfachste und einheitlichste Weg, den ich gefunden habe, ist die Verwendung von lldb-Anweisungen
frame variable -L yourVariableName
.Oder Sie können ihre Antworten kombinieren:
quelle
Dies ist für Swift 3.
Wie bei @CharlieMonroe wollte ich die Adresse als Ganzzahl erhalten. Insbesondere wollte ich, dass die Adresse eines Thread-Objekts als Thread-ID in einem Diagnoseprotokollierungsmodul verwendet wird, wenn kein Thread-Name verfügbar ist.
Basierend auf Charlie Monroes Code habe ich mir Folgendes ausgedacht. Aber Vorsicht, ich bin sehr neu bei Swift, das ist möglicherweise nicht richtig ...
Die letzte Anweisung ist da, weil ich ohne sie Adressen wie 0x60000007DB3F bekommen habe. Die Modulo-Operation in der letzten Anweisung konvertiert diese in 0x7DB3F.
quelle
Meine Lösung für Swift 3
Dieser Code erstellt eine Beschreibung wie die Standardbeschreibung
<MyClass: 0x610000223340>
quelle
Dies ist sicherlich nicht der schnellste oder sicherste Weg, dies zu tun. Aber es funktioniert bei mir. Dadurch kann jede nsobject-Unterklasse diese Eigenschaft übernehmen.
quelle