Есть ли способ имитировать [NSString stringWithFormat:@"%p", myVar]
, из Objective-C, в новом языке Swift?
Например:
let str = "A String"
println(" str value \(str) has address: ?")
swift
debugging
memory-address
apouche
источник
источник
[NSString stringWithFormat:@"%p", myVar]
,myVar
должен быть указатель. В вашем коде Swiftstr
нет указателя. Таким образом, сравнение не относится.Ответы:
Swift 2
Это теперь является частью стандартной библиотеки:
unsafeAddressOf
.Swift 3
Для Swift 3 используйте
withUnsafePointer
:источник
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)
!Примечание: это для справочных типов.
Свифт 4/5:
Печатает адрес памяти someVar. (спасибо @Ying)
Swift 3.1:
Печатает адрес памяти someVar.
источник
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
это можно сделать так:print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
.Unmanaged.passUnretained(someVar).toOpaque()
(не нужно обобщенной спецификации)debugDescription
его в конец.Обратите внимание, что этот ответ был довольно старым. Многие из описанных методов больше не работают. Конкретно
.core
больше нельзя получить доступ.Однако ответ @ drew является правильным и простым:
Итак, ответ на ваши вопросы:
Вот оригинальный ответ, который был помечен правильно (для потомков / вежливости):
Свифт «прячет» указатели, но они все еще существуют под капотом. (потому что это требуется среде выполнения и по причинам совместимости с Objc и C)
Однако есть кое-что знать, но сначала как напечатать адрес памяти строки Swift?
Это печатает адрес памяти строки, если вы откроете XCode -> Debug Workflow -> View Memory и перейдете к напечатанному адресу, вы увидите необработанные данные строки. Поскольку это строковый литерал, это адрес памяти внутри хранилища двоичного файла (а не стека или кучи).
Тем не менее, если вы делаете
Это будет в стеке, потому что строка создается во время выполнения
ПРИМЕЧАНИЕ. .Core._baseAddress не задокументирован, я нашел его в инспекторе переменных, и он может быть скрыт в будущем
_baseAddress доступен не для всех типов, здесь еще один пример с CInt
Где
takesInt
такая вспомогательная функция C?Со стороны Swift эта функция есть
takesInt(intptr: CMutablePointer<CInt>)
, поэтому она передает CMutablePointer в CInt, и вы можете получить его с помощью & varnameФункция печатает
0x7fff5fbfed98
, и по этому адресу памяти вы найдете 289 (в шестнадцатеричном формате). Вы можете изменить его содержимое с помощью*intptr = 123456
Теперь еще кое-что нужно знать.
Строка, по-быстрому, является примитивным типом, а не объектом.
CInt - это тип Swift, сопоставленный с типом C int.
Если вы хотите адрес памяти объекта, вы должны сделать что-то другое.
У Swift есть несколько типов указателей, которые можно использовать при взаимодействии с C, и вы можете прочитать о них здесь: Типы указателей Swift
Более того, вы можете больше узнать о них, изучая их объявление (cmd + click на типе), чтобы понять, как конвертировать тип указателя на другой
printptr
это вспомогательная функция C, которую я создал, с этой реализациейОпять же, напечатан пример адреса:,
0x6000000530b0
и если вы пройдете инспектор памяти, вы найдете свою NSStringОдна вещь, которую вы можете сделать с указателями в Swift (это может быть сделано даже с параметрами inout)
Или, взаимодействуя с Objc / c
источник
Чтобы получить (куча) адрес объекта
( Edit: Swift 1.2 теперь включает в себя аналогичную функцию
unsafeAddressOf
.)В Objective-C это было бы
[NSString stringWithFormat:@"%p", o]
.o
это ссылка на экземпляр. Таким образом, еслиo
назначена другая переменнаяo2
, возвращаемый адрес дляo2
будет таким же.Это не относится к структурам (в том числе
String
) и примитивным типам (напримерInt
), потому что они живут прямо в стеке. Но мы можем получить местоположение в стеке.Чтобы получить (стек) адрес структуры, встроенного типа или ссылки на объект
В Objective-C это будет
[NSString stringWithFormat:@"%p", &o]
или[NSString stringWithFormat:@"%p", &i]
.s
это структура. Таким образом, еслиs
назначена другая переменнаяs2
, значение будет скопировано, а возвращаемый адрес дляs2
будет другим.Как это совмещается (резюме указателя)
Как и в Objective-C, есть два разных адреса, связанных с
o
. Первый - это местоположение объекта, второй - это местоположение ссылки (или указателя) на объект.Да, это означает, что содержимое адреса 0x7fff5fbfe658 является числом 0x6100000011d0, как отладчик может сказать нам:
Таким образом, за исключением строк, являющихся структурами, внутренне все это работает почти так же, как в (Objective-) C.
(Текущий на Xcode 6.3)
источник
TL; DR
( Гист )
В Swift мы имеем дело с типами значений (структурами) или ссылочными типами (классами). При выполнении:
Некоторая память выделяется по адресу X, и по этому адресу мы найдем значение 42. Выполнение
&n
создает указатель, указывающий на адрес X, поэтому&n
сообщает нам, гдеn
находится.При выполнении:
Память выделяется в двух местах:
Как уже говорилось, классы являются ссылочными типами: поэтому значение
c
находится по адресу X, по которому мы найдем значение Y. А по адресу Y + 16 мы найдемfoo
и по адресу Y + 24 мы найдемbar
( в + 0 и + 8 мы найдем данные о типе и количество ссылок, я не могу рассказать вам больше об этом ...).0x2a
42 (foo) и0x54
84 (бар).В обоих случаях использование
&n
или&c
даст нам адрес X. Для типов значений это то, что мы хотим, но не для ссылочных типов.При выполнении:
Мы создаем указатель на ссылку, то есть указатель, который указывает на адрес X. То же самое при использовании
withUnsafePointer(&c) {}
.Теперь, когда мы лучше понимаем, что происходит под капотом, и теперь мы знаем, что по адресу X мы найдем адрес Y (именно тот, который нам нужен), мы можем сделать следующее, чтобы получить его:
Проверка:
Есть и другие способы сделать это:
toOpaque()
на самом деле звонкиunsafeBitCast(c, to: UnsafeMutableRawPointer.self)
.Я надеюсь, что это помогло ... это сделало для меня 😆.
источник
MemoryLocation
выдает 2 разных адреса.Типы ссылок:
===
Оператор идентификации используется для проверки того, что 2 объекта указывают на одну и ту же ссылку.ObjectIdentifier
чтобы получить адрес памятиКод:
Типы значений:
источник
Просто используйте это:
источник
MyClass?
" не соответствует CVarArg, вы можете это сделатьextension Optional : CVarArg { }
. В противном случае это, кажется, печатает адреса без всего "небезопасного" безумия других ответов.var _cVarArgEncoding: [Int]
поCVarArg
. Не ясно, как это должно быть реализовано.Если вы просто хотите увидеть это в отладчике и больше ничего не делать с ним, нет необходимости фактически получать
Int
указатель. Чтобы получить строковое представление адреса объекта в памяти, просто используйте что-то вроде этого:Пример использования:
Кроме того, помните, что вы можете просто напечатать объект, не переопределяя его
description
, и он покажет адрес своего указателя вместе с более информативным (если часто загадочным) текстом.источник
Swift 5
Использование:
источник
Unmanaged.passUnretained(myObject).toOpaque()
вместо этого работает нормально.AnyObject
параметр. Я бы предпочелAny
в качестве типа ввода.В Swift4 про массив:
источник
self?.array
.Другие ответы хороши, хотя я искал способ получить адрес указателя в виде целого числа:
Просто небольшое продолжение.
источник
Ответ @Drew предоставляет только для типа класса.
Ответ @nschum предоставить может быть только для типа структуры.
Однако, если вы используете второй метод, чтобы получить адрес массива с элементом типа value. Swift скопирует весь массив, потому что в Swift массив является копируемым при записи, и Swift не может гарантировать, что он будет вести себя таким образом, как только передаст управление C / C ++ (который запускается с помощью
&
получения адреса). И если вместо этого вы используете первый метод, он автоматически преобразуетсяArray
в то,NSArray
что, безусловно, нам не нужно.Итак, самый простой и унифицированный способ, который я нашел, это использование инструкции lldb
frame variable -L yourVariableName
.Или вы можете объединить свои ответы:
источник
Это для Swift 3.
Как @CharlieMonroe, я хотел получить адрес в виде целого числа. В частности, я хотел, чтобы адрес объекта Thread использовался в качестве идентификатора потока в модуле ведения журнала диагностики для ситуаций, когда имя потока не было доступно.
Основываясь на коде Чарли Монро, вот что я придумал до сих пор. Но будьте осторожны, я очень новичок в Swift, это может быть не правильно ...
Последнее утверждение есть, потому что без него я получал адреса типа 0x60000007DB3F. Операция по модулю в последнем утверждении преобразует это в 0x7DB3F.
источник
Мое решение на Swift 3
этот код создает описание как описание по умолчанию
<MyClass: 0x610000223340>
источник
Это, конечно, не самый быстрый и безопасный способ сделать это. Но это работает для меня. Это позволит любому подклассу nsobject принять это свойство.
источник