无论如何都要用新的快速语言模拟[NSString stringWithFormat:@"%p", myVar]
代码吗?
例如:
let str = "A String"
println(" str value \(str) has address: ?")
答案 0 :(得分:122)
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
打印someVar的内存地址。 (感谢@Ying)
abc
打印someVar的内存地址。
答案 1 :(得分:100)
现在这是标准库的一部分: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
对于Swift 3,请使用withUnsafePointer
:
var str = "A String"
withUnsafePointer(to: &str) {
print(" str value \(str) has address: \($0)")
}
答案 2 :(得分:51)
请注意,这个答案很老了。它描述的许多方法不再有效。具体而言,无法再访问.core
。
然而,@ drew的回答是正确而简单的:
现在这是标准库的一部分:unsafeAddressOf。
所以你的问题的答案是:
println(" str value \(str) has address: \(unsafeAddressOf(str))")
以下是标记正确的原始答案(后人/礼貌):
斯威夫特“隐藏”指针,但它们仍然存在于引擎盖下。 (因为运行时需要它,并且出于与Objc和C的兼容性原因)然而,有一些事情要知道,但首先如何打印Swift String的内存地址?
var aString : String = "THIS IS A STRING"
NSLog("%p", aString.core._baseAddress) // _baseAddress is a COpaquePointer
// example printed address 0x100006db0
如果打开XCode,则打印字符串的内存地址 - &gt;调试工作流程 - &gt;查看内存并转到打印地址,您将看到字符串的原始数据。 由于这是一个字符串文字,因此这是二进制文件存储区内的内存地址(不是堆栈或堆)。
但是,如果你这样做
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
是这样的C辅助函数
void takesInt(int *intptr)
{
printf("%p", intptr);
}
在Swift方面,这个函数是takesInt(intptr: CMutablePointer<CInt>)
,所以CMutablePointer需要一个CInt,你可以用&amp; varname
该函数打印0x7fff5fbfed98
,在此内存地址处,您将找到289(十六进制表示法)。您可以使用*intptr = 123456
现在,还有其他一些事要知道。
字符串,在swift中,是一种原始类型,而不是一个对象
CInt是映射到C int Type的Swift类型
如果你想要一个对象的内存地址,你必须做一些不同的事情
Swift有一些可以在与C交互时使用的指针类型,你可以在这里阅读它们:Swift Pointer Types
此外,你可以更多地了解他们探索他们的声明(cmd +点击类型),了解如何将一种指针转换为另一种
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
,如果您通过内存检查器,您将找到您的NSString
你可以用Swift中的指针做一件事(这甚至可以使用inout参数完成)
func playWithPointer (stringa :AutoreleasingUnsafePointer<NSString>)
{
stringa.memory = "String Updated";
}
var testString : NSString = "test string"
println(testString)
playWithPointer(&testString)
println(testString)
或者,与Objc / c交互
// 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
答案 3 :(得分:19)
func address<T: AnyObject>(o: T) -> Int {
return unsafeBitCast(o, Int.self)
}
class Test {}
var o = Test()
println(NSString(format: "%p", address(o))) // -> 0x7fd5c8700970
(编辑:> Swift 1.2现在包含一个名为unsafeAddressOf
的类似功能。)
在Objective-C中,这将是[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
在Objective-C中,这将是[NSString stringWithFormat:@"%p", &o]
或[NSString stringWithFormat:@"%p", &i]
。
s
是struct。因此,如果将s
分配给另一个变量s2
,则会复制该值,并且s2
的返回地址将会不同。
与Objective-C类似,有两个与o
关联的不同地址。第一个是对象的位置,第二个是对象的引用(或指针)的位置。
是的,这意味着地址0x7fff5fbfe658的内容是数字0x6100000011d0,因为调试器可以告诉我们:
(lldb) x/g 0x7fff5fbfe658
0x7fff5fbfe658: 0x00006100000011d0
所以,除了字符串是结构体之外,在内部这几乎与(Objective-)C中的相同。
(Xcode 6.3的当前版本)
答案 4 :(得分:17)
<强> TL; DR 强>
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
*/
(Gist)
在Swift中,我们处理值类型(结构)或引用类型(类)。在做的时候:
let n = 42 // Int is a structure, i.e. value type
在地址X处分配了一些内存,在此地址我们将找到值42.执行&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(foo),0x54
为84(bar)。
在这两种情况下,使用&n
或&c
都会为我们提供地址X.对于值类型,这是我们想要的,但不是参考类型。
做的时候:
let referencePointer = UnsafeMutablePointer<C>(&c)
我们在引用上创建一个指针,即一个指向地址X的指针。使用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)
现在我们已经更好地了解了幕后发生的事情,现在我们在地址X处找到地址Y(我们想要的那个)我们可以做以下事情来获得它:
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)
。
我希望这有帮助......它为我做了。
答案 5 :(得分:11)
===
标识运算符用于检查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
答案 6 :(得分:8)
如果你只是想在调试器中看到这个而不用它做任何其他事情,那么就不需要实际获得func main() {
data := [][]int{
{1, 2, 3},
{4, 3, 2},
}
for _, intArr := range data {
a := NewA(intArr)
// a:= A{I: ints[0], J: ints[1], K: ints[2]}
fmt.Println(a)
}
}
指针。要在内存中获取对象地址的字符串表示,只需使用以下内容:
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
答案 7 :(得分:8)
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
答案 8 :(得分:5)
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)
}
答案 9 :(得分:5)
只需使用此:
print(String(format: "%p", object))
答案 10 :(得分: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
只是一点点跟进。
答案 11 :(得分:3)
@Drew提供的答案只能用于班级类型 答案@nschum提供的只能是结构类型。
但是,如果使用第二种方法获取具有值类型元素的数组的地址。 Swift将复制整个数组,因为在Swift数组中是copy-on-write而Swift无法确保它一旦将控制传递给C / C ++就会以这种方式运行(这是通过使用&
来获取地址的触发器)。如果您使用第一种方法,它会自动将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
}
答案 12 :(得分:3)
这适用于Swift 3。
和@CharlieMonroe一样,我想把地址作为整数。具体来说,我想要一个Thread对象的地址,用作诊断日志模块中的线程ID,适用于没有线程名称可用的情况。
基于Charlie Monroe的代码,这是我到目前为止所提出的。但要注意,我对Swift来说很新,这可能不正确......
// 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。
答案 13 :(得分:3)
我在Swift 3上的解决方案
extension MyClass: CustomStringConvertible {
var description: String {
return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
}
}
此代码创建描述,如默认描述
<MyClass: 0x610000223340>
答案 14 :(得分: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