[NSString stringWithFormat:@"%p", myVar]
नई स्विफ्ट भाषा में, उद्देश्य-सी से अनुकरण करने के लिए वैसे भी क्या है ?
उदाहरण के लिए:
let str = "A String"
println(" str value \(str) has address: ?")
[NSString stringWithFormat:@"%p", myVar]
नई स्विफ्ट भाषा में, उद्देश्य-सी से अनुकरण करने के लिए वैसे भी क्या है ?
उदाहरण के लिए:
let str = "A String"
println(" str value \(str) has address: ?")
जवाबों:
यह अब मानक पुस्तकालय का हिस्सा है unsafeAddressOf
:।
/// Return an UnsafePointer to the storage used for `object`. There's
/// not much you can do with this other than use it to identify the
/// object
स्विफ्ट 3 के लिए, उपयोग करें withUnsafePointer
:
var str = "A String"
withUnsafePointer(to: &str) {
print(" str value \(str) has address: \($0)")
}
withUnsafePointer
परिणाम में cannot pass immutable value as inout argument
त्रुटि।
print(self.description)
प्रिंट <MyViewController: 0x101c1d580>
, हम इसे एक संदर्भ के रूप में उपयोग करते हैं। var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }
प्रिंट 0x16fde4028
जो स्पष्ट रूप से अलग पता है। कोई समझा सकता है क्यों?
0x101c1d580
उम्मीद के रूप में:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
UnsafePointer
एक संरचना है, इसलिए आपके द्वारा इंगित किए जा रहे पते को प्रिंट करने के लिए (और स्वयं संरचना नहीं) आपको प्रिंट करना होगा String(format: "%p", $0.pointee)
!
नोट: यह संदर्भ प्रकारों के लिए है।
print(Unmanaged.passUnretained(someVar).toOpaque())
कुछVar के मेमोरी एड्रेस को प्रिंट करता है। (@Ying से साभार)
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
कुछVar के मेमोरी एड्रेस को प्रिंट करता है।
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
इसका उपयोग इस तरह किया जा सकता है print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
:।
Unmanaged.passUnretained(someVar).toOpaque()
(कोई ज़रूरत नहीं जेनेरिक विनिर्देश)
debugDescription
अंत में जोड़ने की सलाह दूंगा ।
ध्यान दें कि यह उत्तर काफी पुराना था। कई विधियों का वर्णन है कि यह अब काम नहीं करता है। विशेष .core
रूप से अब एक्सेस नहीं किया जा सकता है।
हालाँकि @ ड्रू का उत्तर सही और सरल है:
यह अब मानक लाइब्रेरी का हिस्सा है: unsafeAddressOf।
तो आपके सवालों का जवाब है:
println(" str value \(str) has address: \(unsafeAddressOf(str))")
यहाँ मूल उत्तर है जो सही अंकित किया गया था (पोस्टीरिटी / राजनीति के लिए):
स्विफ्ट "छुपाता है" संकेत देता है, लेकिन वे अभी भी हुड के नीचे मौजूद हैं। (क्योंकि रनटाइम को इसकी आवश्यकता है, और ओबजैक और सी के साथ संगतता कारणों के लिए)
हालाँकि यह जानने के लिए कुछ चीजें हैं, लेकिन सबसे पहले स्विफ्ट स्ट्रिंग के मेमोरी एड्रेस को कैसे प्रिंट करें?
var aString : String = "THIS IS A STRING"
NSLog("%p", aString.core._baseAddress) // _baseAddress is a COpaquePointer
// example printed address 0x100006db0
यह स्ट्रिंग के मेमोरी एड्रेस को प्रिंट करता है, यदि आप XCode -> डीबग वर्कफ़्लो खोलते हैं -> मेमोरी देखें और मुद्रित पते पर जाएं, तो आपको स्ट्रिंग का कच्चा डेटा दिखाई देगा। चूंकि यह एक स्ट्रिंग शाब्दिक है, यह बाइनरी (स्टैक या ढेर नहीं) के भंडारण के अंदर एक मेमोरी एड्रेस है।
हालांकि, अगर आप
var aString : String = "THIS IS A STRING" + "This is another String"
NSLog("%p", aString.core._baseAddress)
// example printed address 0x103f30020
यह स्टैक पर होगा, क्योंकि रनटाइम पर स्ट्रिंग बनाई जाती है
नोट: .core._baseAddress का दस्तावेजीकरण नहीं किया गया है, मुझे यह चर निरीक्षक में लग रहा है, और यह भविष्य में छिपा हो सकता है
_baseAddress सभी प्रकारों पर उपलब्ध नहीं है, यहाँ CInt के साथ एक और उदाहरण दिया गया है
var testNumber : CInt = 289
takesInt(&testNumber)
takesInt
सी हेल्पर फंक्शन कहाँ होता है
void takesInt(int *intptr)
{
printf("%p", intptr);
}
स्विफ्ट की तरफ, यह फंक्शन है takesInt(intptr: CMutablePointer<CInt>)
, इसलिए यह सीनेट के लिए CMutablePointer लेता है, और आप इसे & varname से प्राप्त कर सकते हैं
फ़ंक्शन प्रिंट करता है 0x7fff5fbfed98
, इस मेमोरी पते पर आपको 289 (हेक्साडेसिमल नोटेशन में) मिलेगा। आप इसकी सामग्री को बदल सकते हैं*intptr = 123456
अब, कुछ अन्य बातें जानने के लिए।
स्ट्रिंग, स्विफ्ट में, एक आदिम प्रकार है, एक वस्तु नहीं है।
CInt C int प्रकार के लिए एक स्विफ्ट प्रकार मैप किया गया है।
यदि आप किसी ऑब्जेक्ट का मेमोरी एड्रेस चाहते हैं, तो आपको कुछ अलग करना होगा।
स्विफ्ट के कुछ पॉइंटर टाइप हैं जिनका उपयोग C के साथ इंटरैक्ट करते समय किया जा सकता है, और आप उनके बारे में यहाँ पढ़ सकते हैं: स्विफ्ट पॉइंटर प्रकार
इसके अलावा, आप उनके बारे में और अधिक जानकारी प्राप्त कर सकते हैं, जो उनके डिक्लेरेशन (टाइप पर क्लिक करें) को समझने के लिए, कि कैसे कन्वर्ट करें। दूसरे में एक प्रकार का सूचक
var aString : NSString = "This is a string" // create an NSString
var anUnmanaged = Unmanaged<NSString>.passUnretained(aString) // take an unmanaged pointer
var opaque : COpaquePointer = anUnmanaged.toOpaque() // convert it to a COpaquePointer
var mut : CMutablePointer = &opaque // this is a CMutablePointer<COpaquePointer>
printptr(mut) // pass the pointer to an helper function written in C
printptr
एक C सहायक समारोह है जिसे मैंने इस कार्यान्वयन के साथ बनाया है
void printptr(void ** ptr)
{
printf("%p", *ptr);
}
फिर, मुद्रित पते का एक उदाहरण: 0x6000000530b0
और यदि आप स्मृति निरीक्षक से गुजरते हैं, तो आपको अपना एनएसएसट्रिंग मिलेगा
स्विफ्ट में पॉइंटर्स के साथ एक चीज आप कर सकते हैं (यह इनऑउट मापदंडों के साथ भी किया जा सकता है)
func playWithPointer (stringa :AutoreleasingUnsafePointer<NSString>)
{
stringa.memory = "String Updated";
}
var testString : NSString = "test string"
println(testString)
playWithPointer(&testString)
println(testString)
या, ओब्जेक्ट / सी के साथ बातचीत
// objc side
+ (void)writeString:(void **)var
{
NSMutableString *aString = [[NSMutableString alloc] initWithFormat:@"pippo %@", @"pluto"];
*var = (void *)CFBridgingRetain(aString); // Retain!
}
// swift side
var opaque = COpaquePointer.null() // create a new opaque pointer pointing to null
TestClass.writeString(&opaque)
var string = Unmanaged<NSString>.fromOpaque(opaque).takeRetainedValue()
println(string)
// this prints pippo pluto
func address<T: AnyObject>(o: T) -> Int {
return unsafeBitCast(o, Int.self)
}
class Test {}
var o = Test()
println(NSString(format: "%p", address(o))) // -> 0x7fd5c8700970
( संपादित करें: स्विफ्ट 1.2 में अब एक समान फ़ंक्शन शामिल है unsafeAddressOf
।)
ऑब्जेक्टिव-सी में यह होगा [NSString stringWithFormat:@"%p", o]
।
o
उदाहरण के लिए एक संदर्भ है। इसलिए यदि o
किसी अन्य चर को सौंपा गया है o2
, तो उसके लिए दिया गया पता o2
समान होगा।
यह संरचना (सहित String
) और आदिम प्रकार (जैसे Int
) पर लागू नहीं होता है , क्योंकि वे सीधे स्टैक पर रहते हैं। लेकिन हम स्टैक पर स्थान पुनः प्राप्त कर सकते हैं।
func address(o: UnsafePointer<Void>) -> Int {
return unsafeBitCast(o, Int.self)
}
println(NSString(format: "%p", address(&o))) // -> 0x10de02ce0
var s = "A String"
println(NSString(format: "%p", address(&s))) // -> 0x10de02ce8
var i = 55
println(NSString(format: "%p", address(&i))) // -> 0x10de02d00
ऑब्जेक्टिव-सी में यह [NSString stringWithFormat:@"%p", &o]
या होगा [NSString stringWithFormat:@"%p", &i]
।
s
संरचना है। इसलिए यदि s
किसी अन्य चर को सौंपा गया है s2
, तो मूल्य की प्रतिलिपि बनाई जाएगी और इसके लिए दिया गया पता s2
अलग होगा।
जैसे ऑब्जेक्टिव-सी में दो अलग-अलग पते जुड़े होते हैं o
। पहला ऑब्जेक्ट का स्थान है, दूसरा ऑब्जेक्ट के लिए संदर्भ (या पॉइंटर) का स्थान है।
हां, इसका मतलब यह है कि पता 0x7fff5fbfe658 की सामग्री संख्या 0x6100000011d0 है क्योंकि डिबगर हमें बता सकता है:
(lldb) x/g 0x7fff5fbfe658
0x7fff5fbfe658: 0x00006100000011d0
इसलिए, स्ट्रिंग्स के स्ट्रक्चर्स को छोड़कर, आंतरिक रूप से यह सभी बहुत अधिक (Objective-) C के समान ही काम करता है।
(वर्तमान में Xcode 6.3 के रूप में)
टी एल; डॉ
struct MemoryAddress<T>: CustomStringConvertible {
let intValue: Int
var description: String {
let length = 2 + 2 * MemoryLayout<UnsafeRawPointer>.size
return String(format: "%0\(length)p", intValue)
}
// for structures
init(of structPointer: UnsafePointer<T>) {
intValue = Int(bitPattern: structPointer)
}
}
extension MemoryAddress where T: AnyObject {
// for classes
init(of classInstance: T) {
intValue = unsafeBitCast(classInstance, to: Int.self)
// or Int(bitPattern: Unmanaged<T>.passUnretained(classInstance).toOpaque())
}
}
/* Testing */
class MyClass { let foo = 42 }
var classInstance = MyClass()
let classInstanceAddress = MemoryAddress(of: classInstance) // and not &classInstance
print(String(format: "%018p", classInstanceAddress.intValue))
print(classInstanceAddress)
struct MyStruct { let foo = 1 } // using empty struct gives weird results (see comments)
var structInstance = MyStruct()
let structInstanceAddress = MemoryAddress(of: &structInstance)
print(String(format: "%018p", structInstanceAddress.intValue))
print(structInstanceAddress)
/* output
0x0000000101009b40
0x0000000101009b40
0x00000001005e3000
0x00000001005e3000
*/
( जिस्ट )
स्विफ्ट में हम या तो मूल्य प्रकारों (संरचनाओं) या संदर्भ प्रकारों (कक्षाओं) से निपटते हैं। जब कर रहे हैं:
let n = 42 // Int is a structure, i.e. value type
पता X पर कुछ मेमोरी आवंटित की गई है, और इस पते पर हमें मान 42 मिलेगा। Doing &n
X को संबोधित करने के लिए एक पॉइंटर बनाता है, इसलिए &n
हमें बताता है कि कहां n
स्थित है।
(lldb) frame variable -L n
0x00000001005e2e08: (Int) n = 42
(lldb) memory read -c 8 0x00000001005e2e08
0x1005e2e08: 2a 00 00 00 00 00 00 00 // 0x2a is 42
जब कर रहे हैं:
class C { var foo = 42, bar = 84 }
var c = C()
मेमोरी दो स्थानों पर आवंटित की जाती है:
जैसा कि कहा गया है, कक्षाएं संदर्भ प्रकार हैं: इसलिए मान का c
पता X पर स्थित है, जिस पर हमें Y का मान मिलेगा। और पते पर Y + 16 हम पाएंगे foo
और पते पर Y + 24 हम पाएंगे bar
( + 0 और + 8 पर हमें टाइप डेटा और संदर्भ संख्याएँ मिलेंगी, मैं आपको इसके बारे में अधिक नहीं बता सकता ...)।
(lldb) frame variable c // gives us address Y
(testmem.C) c = 0x0000000101a08f90 (foo = 42, bar = 84)
(lldb) memory read 0x0000000101a08f90 // reading memory at address Y
0x101a08f90: e0 65 5b 00 01 00 00 00 02 00 00 00 00 00 00 00
0x101a08fa0: 2a 00 00 00 00 00 00 00 54 00 00 00 00 00 00 00
0x2a
42 (फू) है और 0x54
84 (बार) है।
दोनों ही मामलों में, हमें X का उपयोग करना &n
या &c
उसका पता देना होगा। मूल्य प्रकारों के लिए, यही हम चाहते हैं, लेकिन संदर्भ प्रकारों के लिए नहीं है।
जब कर रहे हैं:
let referencePointer = UnsafeMutablePointer<C>(&c)
हम संदर्भ पर एक पॉइंटर बनाते हैं, यानी एक पॉइंटर जो एक्स का उपयोग करते समय पता करने के लिए इंगित करता है withUnsafePointer(&c) {}
।
(lldb) frame variable referencePointer
(UnsafeMutablePointer<testmem.C>) referencePointer = 0x00000001005e2e00 // address X
(lldb) memory read -c 8 0x00000001005e2e00 // read memory at address X
0x1005e2e00: 20 ec 92 01 01 00 00 00 // contains address Y, consistent with result below:
(lldb) frame variable c
(testmem.C) c = 0x000000010192ec20 (foo = 42, bar = 84)
अब जब हमें हुड के नीचे क्या हो जाता है, इसकी बेहतर समझ है, और अब हम जानते हैं कि एक्स पर हमें पता वाई मिलेगा (जिसे हम चाहते हैं) हम इसे प्राप्त करने के लिए निम्नलिखित कर सकते हैं:
let addressY = unsafeBitCast(c, to: Int.self)
सत्यापित किया जा रहा:
(lldb) frame variable addressY -f hex
(Int) addressY = 0x0000000101b2fd20
(lldb) frame variable c
(testmem.C) c = 0x0000000101b2fd20 (foo = 42, bar = 84)
ऐसा करने के अन्य तरीके हैं:
let addressY1 = Int(bitPattern: Unmanaged.passUnretained(c).toOpaque())
let addressY2 = withUnsafeMutableBytes(of: &c) { $0.load(as: Int.self) }
toOpaque()
वास्तव में कहता है unsafeBitCast(c, to: UnsafeMutableRawPointer.self)
।
मुझे उम्मीद है कि इससे मदद मिली ... इसने मेरे लिए it किया।
MemoryLocation
2 अलग-अलग पतों के उत्पादन के 2 अलग- अलग उदाहरणों के माध्यम से एक ही संरचना के पते को प्रिंट करने की कोशिश करते हुए ।
===
पहचान ऑपरेटर का उपयोग एक ही संदर्भ में 2 ऑब्जेक्ट्स पॉइंट को चेक करने के लिए किया जाता है।ObjectIdentifier
मेमोरी एड्रेस प्राप्त करने के लिए उपयोग करेंclass C {}
let c1 = C()
let c2 = c1
//Option 1:
print("c1 address: \(Unmanaged.passUnretained(c1).toOpaque())")
//Option 2:
let o1 = ObjectIdentifier(c1)
let o2 = ObjectIdentifier(c2)
print("o1 -> c1 = \(o1)")
print("o2 -> c2 = \(o2)")
if o1 == o2 {
print("c1 = c2")
} else {
print("c1 != c2")
}
//Output:
//c1 address: 0x000060c000005b10
//o1 -> c1 = ObjectIdentifier(0x000060c000005b10)
//o2 -> c2 = ObjectIdentifier(0x000060c000005b10)
//c1 = c2
बस इस का उपयोग करें:
print(String(format: "%p", object))
MyClass?
सीवीआरएआरजी के अनुरूप कंपाइलर शिकायत नहीं मिलती है, तो आप कर सकते हैं extension Optional : CVarArg { }
। अन्यथा यह अन्य उत्तरों के सभी "असुरक्षित" पागलपन के बिना पते को प्रिंट करने के लिए लगता है।
var _cVarArgEncoding: [Int]
पर CVarArg
। स्पष्ट नहीं है कि इसे कैसे लागू किया जाना चाहिए।
यदि आप इसे डीबगर में देखना चाहते हैं और इसके साथ कुछ और नहीं करते हैं, तो वास्तव में Int
पॉइंटर प्राप्त करने की कोई आवश्यकता नहीं है । स्मृति में किसी ऑब्जेक्ट के पते का स्ट्रिंग प्रतिनिधित्व प्राप्त करने के लिए, बस कुछ इस तरह का उपयोग करें:
public extension NSObject { // Extension syntax is cleaner for my use. If your needs stem outside NSObject, you may change the extension's target or place the logic in a global function
public var pointerString: String {
return String(format: "%p", self)
}
}
उदाहरण उपयोग:
print(self.pointerString, "Doing something...")
// Prints like: 0x7fd190d0f270 Doing something...
इसके अतिरिक्त, याद रखें कि आप किसी ऑब्जेक्ट को बिना ओवरराइड किए प्रिंट कर सकते हैंdescription
, और यह इसके पॉइंटर एड्रेस को और अधिक वर्णनात्मक (यदि बार-बार गुप्त) पाठ के साथ दिखाएगा।
print(self, "Doing something else...")
// Prints like: <MyModule.MyClass: 0x7fd190d0f270> Doing something else...
// Sometimes like: <_TtCC14__lldb_expr_668MyModule7MyClass: 0x7fd190d0f270> Doing something else...
extension String {
static func pointer(_ object: AnyObject?) -> String {
guard let object = object else { return "nil" }
let opaque: UnsafeMutableRawPointer = Unmanaged.passUnretained(object).toOpaque()
return String(describing: opaque)
}
}
print("FileManager.default: \(String.pointer(FileManager.default))")
// FileManager.default: 0x00007fff5c287698
print("nil: \(String.pointer(nil))")
// nil: nil
Unmanaged.passUnretained(myObject).toOpaque()
इसके बजाय ठीक से काम करता है।
AnyObject
पैरामीटर लेता है । मैं Any
इनपुट प्रकार के रूप में पसंद करूंगा ।
let array1 = [1,2,3]
let array2 = array1
array1.withUnsafeBufferPointer { (point) in
print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
}
array2.withUnsafeBufferPointer { (point) in
print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
}
self?.array
।
अन्य उत्तर ठीक हैं, हालांकि मैं एक पूर्णांक के रूप में पॉइंटर पता प्राप्त करने का एक तरीका ढूंढ रहा था:
let ptr = unsafeAddressOf(obj)
let nullPtr = UnsafePointer<Void>(bitPattern: 0)
/// This gets the address of pointer
let address = nullPtr.distanceTo(ptr) // This is Int
बस थोड़ा सा फॉलोवर।
उत्तर @Drew प्रदान केवल वर्ग प्रकार के लिए इस्तेमाल किया जा सकता है।
उत्तर @nschum प्रदान केवल संरचनात्मक प्रकार के लिए हो सकता है।
हालाँकि अगर आप किसी प्रकार का मान पाने के लिए दूसरी विधि का उपयोग करते हैं, जिसमें वैल्यू टाइप एलीमेंट होता है। स्विफ्ट पूरे ऐरे को कॉपी करेगा क्योंकि स्विफ्ट एरे में कॉपी-ऑन-राइट है और स्विफ्ट यह सुनिश्चित नहीं कर सकती है कि सी / सी ++ पर नियंत्रण पास होने के बाद यह इस तरह से व्यवहार करे (जो &
एड्रेस पाने के लिए उपयोग करके ट्रिगर होता है )। और अगर आप इसके बजाय पहली विधि का उपयोग करते हैं, तो यह स्वचालित रूप से परिवर्तित Array
हो जाएगा NSArray
जो निश्चित रूप से कुछ ऐसा है जो हम नहीं चाहते हैं।
इसलिए मैंने पाया सबसे सरल और एकीकृत तरीका lldb अनुदेश का उपयोग कर रहा है frame variable -L yourVariableName
।
या आप उनके उत्तर जोड़ सकते हैं:
func address(o: UnsafePointer<Void>) {
let addr = unsafeBitCast(o, Int.self)
print(NSString(format: "%p", addr))
}
func address<T: AnyObject>(o: T) -> String{
let addr = unsafeBitCast(o, Int.self)
return NSString(format: "%p", addr) as String
}
यह स्विफ्ट 3 के लिए है।
@CharlieMonroe की तरह मैं एक पूर्णांक के रूप में पता प्राप्त करना चाहता था। विशेष रूप से, मैं निदान लॉगिंग मॉड्यूल में थ्रेड आईडी के रूप में उपयोग के लिए एक थ्रेड ऑब्जेक्ट का पता चाहता था, उन स्थितियों के लिए जहां कोई थ्रेड नाम उपलब्ध नहीं था।
चार्ली मुनरो के कोड के आधार पर, यहाँ अब तक मैं जो कुछ भी करता आया हूँ। लेकिन सावधान, मैं स्विफ्ट के लिए बहुत नया हूँ, यह सही नहीं हो सकता है ...
// Convert the memory address of the current Thread object into an Int for use as a thread ID
let objPtr = Unmanaged.passUnretained(Thread.current).toOpaque()
let onePtr = UnsafeMutableRawPointer(bitPattern: 1)! // 1 used instead of 0 to avoid crash
let rawAddress : Int64 = onePtr.distance(to: objPtr) + 1 // This may include some high-order bits
let address = rawAddress % (256 * 1024 * 1024 * 1024) // Remove high-order bits
अंतिम बयान वहाँ है क्योंकि इसके बिना मुझे 0x60000007DB3F जैसे पते मिल रहे थे। अंतिम कथन में मोडुलो ऑपरेशन को 0x7DB3F में परिवर्तित करता है।
स्विफ्ट 3 पर मेरा समाधान
extension MyClass: CustomStringConvertible {
var description: String {
return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
}
}
यह कोड डिफ़ॉल्ट विवरण की तरह विवरण बनाता है
<MyClass: 0x610000223340>
यह निश्चित रूप से इसके बारे में जाने का सबसे तेज़ या सबसे सुरक्षित तरीका नहीं है। लेकिन यह मेरे लिए काम कर गया। यह किसी भी nsobject उपवर्ग को इस संपत्ति को अपनाने की अनुमति देगा।
public extension NSObject {
public var memoryAddress : String? {
let str = "\(self.self)".components(separatedBy: ": ")
guard str.count > 1 else { return nil }
return str[1].replacingOccurrences(of: ">", with: "")
}
}
//usage
let foo : String! = "hello"
Swift.print(foo.memoryAddress) // prints 0x100f12980
[NSString stringWithFormat:@"%p", myVar]
,myVar
एक सूचक होना चाहिए। आपके स्विफ्ट कोड में,str
एक पॉइंटर नहीं है। इसलिए तुलना लागू नहीं होती है।