Existe alguma maneira de simular o [NSString stringWithFormat:@"%p", myVar]
, do Objective-C, na nova linguagem Swift?
Por exemplo:
let str = "A String"
println(" str value \(str) has address: ?")
swift
debugging
memory-address
apouche
fonte
fonte
[NSString stringWithFormat:@"%p", myVar]
,myVar
deve ser um ponteiro. No seu código Swift,str
não é um ponteiro. Portanto, a comparação não se aplica.Respostas:
Swift 2
Esta é agora parte da biblioteca padrão:
unsafeAddressOf
.Swift 3
Para o Swift 3, use
withUnsafePointer
:fonte
withUnsafePointer
resulta emcannot pass immutable value as inout argument
erro.print(self.description)
impressões<MyViewController: 0x101c1d580>
, usamos como referência.var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }
imprime0x16fde4028
um endereço claramente diferente. Alguém pode explicar o porquê?0x101c1d580
conforme o esperado:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
UnsafePointer
é uma estrutura, portanto, para imprimir o endereço que está apontando (e não a estrutura em si), você precisa imprimirString(format: "%p", $0.pointee)
!Nota: Isto é para tipos de referência.
Swift 4/5:
Imprime o endereço de memória de someVar. (graças a @Ying)
Swift 3.1:
Imprime o endereço de memória de someVar.
fonte
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
isso pode ser feito da seguinte forma:print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
.Unmanaged.passUnretained(someVar).toOpaque()
(sem necessidade de especificação genérico)debugDescription
ao final dela.Observe que essa resposta era bastante antiga. Muitos dos métodos descritos não funcionam mais. Especificamente
.core
não pode mais ser acessado.No entanto, a resposta de @ drew é correta e simples:
Portanto, a resposta para suas perguntas é:
Aqui está a resposta original que foi marcada como correta (para posteridade / polidez):
Swift "esconde" ponteiros, mas eles ainda existem sob o capô. (porque o tempo de execução precisa dele e por motivos de compatibilidade com Objc e C)
Existem poucas coisas para saber, no entanto, mas primeiro como imprimir o endereço de memória de uma Swift String?
Isso imprime o endereço de memória da string, se você abrir XCode -> Debug Workflow -> View Memory e acessar o endereço impresso, verá os dados brutos da string. Como essa é uma string literal, é um endereço de memória dentro do armazenamento do binário (não pilha ou pilha).
No entanto, se você fizer
Isso estará na pilha, porque a sequência é criada em tempo de execução
NOTA: .core._baseAddress não está documentado, achei-o no inspetor de variáveis e pode estar oculto no futuro
_baseAddress não está disponível em todos os tipos, aqui outro exemplo com um CInt
Onde
takesInt
está uma função auxiliar C como estaNo lado Swift, essa função é
takesInt(intptr: CMutablePointer<CInt>)
, portanto, leva um CMutablePointer para um CInt e você pode obtê-lo com & varnameA função imprime
0x7fff5fbfed98
, e neste endereço de memória você encontrará 289 (em notação hexadecimal). Você pode alterar seu conteúdo com*intptr = 123456
Agora, outras coisas a saber.
String, em rápida, é um tipo primitivo, não um objeto.
CInt é um tipo Swift mapeado para o tipo C int.
Se você deseja o endereço de memória de um objeto, precisa fazer algo diferente.
O Swift possui alguns tipos de ponteiros que podem ser usados ao interagir com C, e você pode ler sobre eles aqui: Tipos de ponteiros rápidos
Além disso, você pode entender mais sobre eles explorando sua declaração (cmd + clique no tipo) para entender como converter um tipo de ponteiro para outro
printptr
é uma função auxiliar C que eu criei, com esta implementaçãoNovamente, um exemplo do endereço impresso:,
0x6000000530b0
e se você passar pelo inspetor de memória, encontrará seu NSStringUma coisa que você pode fazer com os ponteiros no Swift (isso pode ser feito com parâmetros inout)
Ou, interagindo com Objc / c
fonte
Para obter o endereço (heap) de um objeto
( Edit: Swift 1.2 agora inclui uma função semelhante chamada
unsafeAddressOf
.)No Objetivo-C, isso seria
[NSString stringWithFormat:@"%p", o]
.o
é uma referência à instância. Portanto, seo
for atribuído a outra variávelo2
, o endereço retornadoo2
será o mesmo.Isso não se aplica a estruturas (incluindo
String
) e tipos primitivos (comoInt
), porque eles vivem diretamente na pilha. Mas podemos recuperar a localização na pilha.Para obter o endereço (pilha) de uma estrutura, tipo incorporado ou referência de objeto
No Objetivo-C, isso seria
[NSString stringWithFormat:@"%p", &o]
ou[NSString stringWithFormat:@"%p", &i]
.s
é struct. Portanto, ses
for atribuído a outra variávels2
, o valor será copiado e o endereço retornados2
será diferente.Como ele se encaixa (recapitulação do ponteiro)
Como no Objective-C, existem dois endereços diferentes associados
o
. A primeira é a localização do objeto, a segunda é a localização da referência (ou ponteiro) para o objeto.Sim, isso significa que o conteúdo do endereço 0x7fff5fbfe658 é o número 0x6100000011d0, conforme o depurador pode nos dizer:
Portanto, exceto que strings são structs, internamente, tudo isso funciona da mesma forma que em (Objective-) C.
(Atual a partir do Xcode 6.3)
fonte
TL; DR
( Gist )
No Swift, lidamos com tipos de valor (estruturas) ou tipos de referência (classes). Ao fazer:
Alguma memória é alocada no endereço X e, nesse endereço, encontraremos o valor 42. Doing
&n
cria um ponteiro apontando para o endereço X e, portanto,&n
informa onden
está localizado.Ao fazer:
A memória é alocada em dois locais:
Como dito, as classes são tipos de referência: portanto, o valor de
c
está localizado no endereço X, no qual encontraremos o valor de Y. E no endereço Y + 16, encontraremosfoo
e no endereço Y + 24, encontraremosbar
( em + 0 e + 8, encontraremos dados de tipo e contagem de referência; não posso contar muito mais sobre isso ...).0x2a
é 42 (foo) e0x54
é 84 (bar).Nos dois casos, usar
&n
ou&c
nos fornecerá o endereço X. Para os tipos de valor, é isso que queremos, mas não para os tipos de referência.Ao fazer:
Criamos um ponteiro na referência, ou seja, um ponteiro que aponta para o endereço X. A mesma coisa ao usar
withUnsafePointer(&c) {}
.Agora que temos uma melhor compreensão do que acontece sob o capô e que agora no endereço X encontramos o endereço Y (que é o que queremos), podemos fazer o seguinte para obtê-lo:
Verificando:
Existem outras maneiras de fazer isso:
toOpaque()
realmente chamaunsafeBitCast(c, to: UnsafeMutableRawPointer.self)
.Espero que isso tenha ajudado ... ajudou por mim 😆.
fonte
MemoryLocation
produz 2 endereços diferentes.Tipos de referência:
===
O operador de identidade é usado para verificar 2 objetos que apontam para a mesma referência.ObjectIdentifier
para obter o endereço de memóriaCódigo:
Tipos de valor:
fonte
Apenas use isto:
fonte
MyClass?
" não estiver em conformidade com o CVarArg, poderá fazê-loextension Optional : CVarArg { }
. Caso contrário, isso parece imprimir endereços sem toda a insanidade "insegura" das outras respostas.var _cVarArgEncoding: [Int]
onCVarArg
. Não está claro como isso deve ser implementado.Se você deseja apenas ver isso no depurador e não fazer mais nada com ele, não há necessidade de obter o
Int
ponteiro. Para obter a representação em cadeia do endereço de um objeto na memória, use algo como isto:Exemplo de uso:
Além disso, lembre-se de que você pode simplesmente imprimir um objeto sem substituí-
description
lo, e ele mostrará o endereço do ponteiro ao lado de um texto mais descritivo (se bem que enigmático).fonte
Swift 5
Uso:
fonte
Unmanaged.passUnretained(myObject).toOpaque()
funciona corretamente.AnyObject
parâmetro. Eu prefeririaAny
como o tipo de entrada.Em Swift4 sobre Matriz:
fonte
self?.array
.As outras respostas são boas, embora eu estivesse procurando uma maneira de obter o endereço do ponteiro como um número inteiro:
Apenas um pequeno acompanhamento.
fonte
A resposta que @Drew fornece pode ser usada apenas para o tipo de classe.
A resposta que @nschum fornece pode ser apenas para o tipo struct.
No entanto, se você usar o segundo método para obter o endereço de uma matriz com o elemento do tipo de valor. O Swift copiará toda a matriz porque na matriz Swift é cópia na gravação e a Swift não pode se comportar dessa maneira depois de passar o controle para o C / C ++ (que é acionado usando
&
para obter o endereço). E se você usar o primeiro método, ele será convertido automaticamenteArray
para oNSArray
que certamente é algo que não queremos.Portanto, a maneira mais simples e unificada que encontrei é usar a instrução lldb
frame variable -L yourVariableName
.Ou você pode combinar as respostas deles:
fonte
Isto é para o Swift 3.
Como @CharlieMonroe, eu queria obter o endereço como um número inteiro. Especificamente, eu queria o endereço de um objeto Thread para uso como um ID de thread em um módulo de log de diagnóstico, para situações em que nenhum nome de thread estivesse disponível.
Baseado no código de Charlie Monroe, aqui está o que eu criei até agora. Mas cuidado, eu sou muito novo no Swift, isso pode não estar correto ...
A última declaração está lá porque, sem ela, eu estava obtendo endereços como 0x60000007DB3F. A operação do módulo na última instrução converte isso em 0x7DB3F.
fonte
Minha solução no Swift 3
esse código cria descrição como descrição padrão
<MyClass: 0x610000223340>
fonte
Certamente, essa não é a maneira mais rápida ou segura de fazer isso. Mas funciona para mim. Isso permitirá que qualquer subclasse nsobject adote essa propriedade.
fonte