स्विफ्ट में वैरिएबल मेमोरी एड्रेस प्रिंट करना


166

[NSString stringWithFormat:@"%p", myVar]नई स्विफ्ट भाषा में, उद्देश्य-सी से अनुकरण करने के लिए वैसे भी क्या है ?

उदाहरण के लिए:

let str = "A String"
println(" str value \(str) has address: ?")

2
में [NSString stringWithFormat:@"%p", myVar], myVarएक सूचक होना चाहिए। आपके स्विफ्ट कोड में, strएक पॉइंटर नहीं है। इसलिए तुलना लागू नहीं होती है।
user102008

5
यह ध्यान देने योग्य है, कम से कम जब मैं इसे टाइप कर रहा हूं, तो उपरोक्त दो टिप्पणियां गलत हैं।
बेन लेगियरियो

जवाबों:


112

स्विफ्ट 2

यह अब मानक पुस्तकालय का हिस्सा है 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

स्विफ्ट 3 के लिए, उपयोग करें withUnsafePointer:

var str = "A String"
withUnsafePointer(to: &str) {
    print(" str value \(str) has address: \($0)")
}

2
unsafeAddressOf () केवल क्लास के प्रकारों के लिए काम करता है (जैसा कि @ नीचे इंगित करता है)। इस प्रकार, यह उत्तर केवल तभी काम करता है जब फाउंडेशन आयात किया जाता है और स्ट्रिंग NSString के लिए ब्रिज किया जाता है। सादे स्विफ्ट में, स्ट्रिंग एक मूल्य प्रकार है और unsafeAddressOf इसका पता (संकलन त्रुटि में प्रयास परिणाम) लेने के लिए उपयोग नहीं किया जा सकता है।
स्टीफन स्काउब

29
क्या होगा यदि मैं स्विफ्ट 3 के साथ अपरिवर्तनीय मूल्य का पता प्रिंट करना चाहता हूं ? withUnsafePointerपरिणाम में cannot pass immutable value as inout argumentत्रुटि।
अलेक्जेंडर वासेन

12
भले ही यह स्वीकार किया जाता है और सबसे ज्यादा वोट दिया जाता है, फिर भी यह गलत परिणाम देता है । उदाहरण: print(self.description)प्रिंट <MyViewController: 0x101c1d580>, हम इसे एक संदर्भ के रूप में उपयोग करते हैं। var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }प्रिंट 0x16fde4028जो स्पष्ट रूप से अलग पता है। कोई समझा सकता है क्यों?
अलेक्जेंडर वासिनिन

4
BTW, इस प्रिंट की 0x101c1d580उम्मीद के रूप में:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
अलेक्जेंडर वैसिन

8
@nyg आपके उत्तर ने मुझे वास्तविक त्रुटि के कारण के लिए एक संकेत दिया: UnsafePointerएक संरचना है, इसलिए आपके द्वारा इंगित किए जा रहे पते को प्रिंट करने के लिए (और स्वयं संरचना नहीं) आपको प्रिंट करना होगा String(format: "%p", $0.pointee)!
अलेक्जेंडर वासेन

214

नोट: यह संदर्भ प्रकारों के लिए है।

स्विफ्ट 4/5:

print(Unmanaged.passUnretained(someVar).toOpaque())

कुछVar के मेमोरी एड्रेस को प्रिंट करता है। (@Ying से साभार)


स्विफ्ट 3.1:

print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())

कुछVar के मेमोरी एड्रेस को प्रिंट करता है।



2
Xcode 8.2.1 ऑटोकार्ट मुझे बता रहा है कि यह अब हैprint(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
जेफ

2
क्या यह सही नहीं होगा यदि someVar एक वस्तु है। यदि कोई समर वैल्यू टाइप होता है जैसे कि एक स्ट्रक्चर, यह हर बार निष्पादित होने पर एक अलग एड्रेस देगा।
आउटऑनवेकेंड

3
@OutOnAWeekend आप सही कह रहे हैं, संभवत: क्योंकि तर्क के रूप में पारित होने पर संरचना की नकल की जाती है। Unmanagedइसका उपयोग इस तरह किया जा सकता है print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque()):।
nyg

1
स्विफ्ट 4 के रूप में, मैं इस झुकाव को प्रिंट करने में सक्षम था - Unmanaged.passUnretained(someVar).toOpaque()(कोई ज़रूरत नहीं जेनेरिक विनिर्देश)
यिंग

2
स्विफ्ट 4 का जवाब एकदम सही है। यदि आप भी मुद्रण के बिना स्ट्रिंग प्रतिनिधित्व प्राप्त करना चाहते हैं, तो मैं इसके debugDescriptionअंत में जोड़ने की सलाह दूंगा ।
पैट्रिक

51

ध्यान दें कि यह उत्तर काफी पुराना था। कई विधियों का वर्णन है कि यह अब काम नहीं करता है। विशेष .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

हां, पॉइंटर को एक्साइट करना होगा, लेकिन न केवल संगतता कारणों के लिए, जैसा कि आपने संदर्भित किया है। संकेत आमतौर पर ऑपरेटिंग सिस्टम द्वारा उपयोग किया जाता है। भले ही भाषा उच्च-स्तरीय भाषा हो, ऑपरेटिंग सिस्टम के इंजन में किसी भी समय किसी भी भाषा में पॉइंटर्स मौजूद होने चाहिए।
होलेक्स

मैंने कहा "अनुकूलता के कारण और क्योंकि रनटाइम की जरूरत है" :-) दूसरा कथन आप जो कह रहे हैं उसे
दोहराते

मुझे लगता है कि यह अब लागू नहीं होता है?
एलेक्लेरसन सेप

हाँ। मैंने @ उत्तर को उसमें से सही उत्तर संपादित किया।
Rog

@LombaX हम केवल संदर्भ प्रकार का पता प्रिंट कर सकते हैं? क्या मैं चर का पता नहीं छाप सकता?
अभिमन्यु

21

किसी वस्तु का (ढेर) पता प्राप्त करना

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 के रूप में)


हम्म। किसी वस्तु की संपत्ति का स्टैक पता प्राप्त करना सुसंगत नहीं है। कोई विचार? इस जिस्ट की जाँच करें!
एलेक्लेरसन

ऑब्जेक्ट के गुण ढेर पर हैं, स्टैक पर नहीं। जब आप एक क्लास इंस्टेंस की संपत्ति को अनसैफेपॉइंट के रूप में पास करते हैं, तो स्विफ्ट वास्तव में पहले मूल्य की प्रतिलिपि बनाता है और आपको कॉपी का पता मिलता है। मुझे संदेह है कि सी कोड को ऑब्जेक्ट के इंटरफ़ेस को दरकिनार करने और असंगत स्थिति पैदा करने से रोकना है। मुझे नहीं पता कि उसके आसपास कोई रास्ता है या नहीं।
nschum


20

टी एल; डॉ

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 &nX को संबोधित करने के लिए एक पॉइंटर बनाता है, इसलिए &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()

मेमोरी दो स्थानों पर आवंटित की जाती है:

  • पता Y पर जहां कक्षा आवृत्ति डेटा स्थित है और
  • पता X पर जहां कक्षा का उदाहरण संदर्भ स्थित है।

जैसा कि कहा गया है, कक्षाएं संदर्भ प्रकार हैं: इसलिए मान का 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

0x2a42 (फू) है और 0x5484 (बार) है।

दोनों ही मामलों में, हमें 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 किया।


बस देखा कि MemoryLocation2 अलग-अलग पतों के उत्पादन के 2 अलग- अलग उदाहरणों के माध्यम से एक ही संरचना के पते को प्रिंट करने की कोशिश करते हुए ।
user1046037

@ user1046037 धन्यवाद, वर्ग init के लिए परिवर्तन किया। मुझे दो अलग-अलग पते भी मिलते हैं, लेकिन केवल जब मैं एक खाली संरचना का उपयोग करता हूं। खाली संरचना का उपयोग हमेशा मुझे अजीब परिणाम देता है। मेरा अनुमान है कि कंपाइलर कुछ अनुकूलन करता है ...
nyg

@ user1046037 की जांच: pastebin.com/mpd3ujw2 । जाहिरा तौर पर, एक ही मेमोरी पते पर सभी खाली संरचना बिंदु। हालाँकि, जब हम पॉइंटर को एक वैरिएबल में स्टोर करना चाहते हैं तो यह उसकी (या स्ट्रक्चर की?) कॉपी कर देगा ...
nyg

यह दिलचस्प है लेकिन जब दो बार छपा तो यह अलग-अलग मेमोरी एड्रेस को प्रिंट करता है। उपरोक्त मामलों में भी ऐसा ही है।
user1046037

@ user1046037 मुझे यकीन नहीं है कि मैं समझ सकता हूं कि आपका क्या मतलब है, क्या आपके पास कुछ कोड है? (मुझे हमेशा एक ही मेमोरी पता मिलता है)
nyg

15

संदर्भ प्रकार:

  • यह एक संदर्भ प्रकार की स्मृति पता प्राप्त करने के लिए समझ में आता है क्योंकि यह पहचान का प्रतिनिधित्व करता है।
  • === पहचान ऑपरेटर का उपयोग एक ही संदर्भ में 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

मूल्य प्रकार:

  • एक मूल्य प्रकार की स्मृति पता प्राप्त करने की आवश्यकता अधिक महत्व नहीं है (जैसा कि यह एक मूल्य है) और जोर मूल्य की समानता पर अधिक होगा।

12

बस इस का उपयोग करें:

print(String(format: "%p", object))

यदि आपको MyClass?सीवीआरएआरजी के अनुरूप कंपाइलर शिकायत नहीं मिलती है, तो आप कर सकते हैं extension Optional : CVarArg { }। अन्यथा यह अन्य उत्तरों के सभी "असुरक्षित" पागलपन के बिना पते को प्रिंट करने के लिए लगता है।
डेविन लेन

यह के कार्यान्वयन की आवश्यकता var _cVarArgEncoding: [Int]पर CVarArg। स्पष्ट नहीं है कि इसे कैसे लागू किया जाना चाहिए।
युकेन झोंग

10

यदि आप इसे डीबगर में देखना चाहते हैं और इसके साथ कुछ और नहीं करते हैं, तो वास्तव में 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...

1
कृपया टिप्पणी के साथ किसी भी डाउनवोट के साथ बताएं कि क्यों, इसलिए मैं और यहां आने वाला कोई भी व्यक्ति जानता है कि यह एक खराब समाधान क्यों है :)
बेन लेगिएरियो

1
सरल और साफ!
बदनगनेश

9

स्विफ्ट 5

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()इसके बजाय ठीक से काम करता है।
पैड्रिग

@ IPadraig धन्यवाद, मैंने आपके कोड के साथ अपडेट किया है। अफसोस की बात है कि यह अब एक AnyObjectपैरामीटर लेता है । मैं Anyइनपुट प्रकार के रूप में पसंद करूंगा ।
neoneye

6

Swift4 में ऐरे के बारे में:

    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)
    }

1
मेरा दिन बचाया। एक बैज होना चाहिए "सबसे उपयोगी हाल ही में इतना अधिग्रहण"
एंटोन ट्रोपास्को

वास्तव में, यह एकमात्र तरीका है जिसने मेरी छाप दी self?.array
रोस्टीस्लाव ड्रूज़ेन्को

4

अन्य उत्तर ठीक हैं, हालांकि मैं एक पूर्णांक के रूप में पॉइंटर पता प्राप्त करने का एक तरीका ढूंढ रहा था:

let ptr = unsafeAddressOf(obj)
let nullPtr = UnsafePointer<Void>(bitPattern: 0)

/// This gets the address of pointer
let address = nullPtr.distanceTo(ptr) // This is Int

बस थोड़ा सा फॉलोवर।


स्विफ्ट 3 के लिए इस उत्तर के एक संस्करण के लिए नीचे देखें।
RenniePet

3

उत्तर @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

यह स्विफ्ट 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

स्विफ्ट 3 पर मेरा समाधान

extension MyClass: CustomStringConvertible {
    var description: String {
        return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
    }
}

यह कोड डिफ़ॉल्ट विवरण की तरह विवरण बनाता है <MyClass: 0x610000223340>


2

यह निश्चित रूप से इसके बारे में जाने का सबसे तेज़ या सबसे सुरक्षित तरीका नहीं है। लेकिन यह मेरे लिए काम कर गया। यह किसी भी 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

प्रतिक्रिया जेफ के लिए धन्यवाद, मैं जवाब का अद्यतन करूंगा
चार्लटन प्रोवेटास

1
कोई बात नहीं! यह मेरी गलती थी! आपका कोड शुद्ध स्विफ्ट क्लास के साथ ठीक काम करता है। गलती के लिये क्षमा करे।
जेफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.