2014-11-21 12 views
10

ho trovato il seguente codice compila e funziona:String valore al UnsafePointer comportamento parametro <UInt8> funzione

func foo(p:UnsafePointer<UInt8>) { 
    var p = p 
    for p; p.memory != 0; p++ { 
     print(String(format:"%2X", p.memory)) 
    } 
} 

let str:String = "今日" 
foo(str) 

Questo stampa E4BB8AE697A5 e che è una rappresentazione UTF-8 valida 今日

Per quanto ne so, questo è un comportamento non documentato. da the document:

Quando una funzione è dichiarata come prendere un argomento UnsafePointer, può accettare qualsiasi dei seguenti:

  • zero, che viene passato come un puntatore nullo
  • Un UnsafePointer, UnsafeMutablePointer, o AutoreleasingUnsafeMutablePointer value, che viene convertito in UnsafePointer se necessario
  • Un'espressione in-out il cui operando è un lvalue di tipo Type, che viene passato come indirizzo del lvalue
  • valore
  • A [Tipo], che è passato come puntatore all'inizio dell'array, e la durata, estesa per tutta la durata della chiamata

In questo caso, è non str di loro.

Mi manca qualcosa?


aggiunto:

E non funziona se il tipo di parametro è UnsafePointer<UInt16>

func foo(p:UnsafePointer<UInt16>) { 
    var p = p 
    for p; p.memory != 0; p++ { 
     print(String(format:"%4X", p.memory)) 
    } 
} 
let str:String = "今日" 
foo(str) 
//^'String' is not convertible to 'UnsafePointer<UInt16>' 

Anche se il String rappresentazione interna è UTF16

let str = "今日" 
var p = UnsafePointer<UInt16>(str._core._baseAddress) 
for p; p.memory != 0; p++ { 
    print(String(format:"%4X", p.memory)) // prints 4ECA65E5 which is UTF16 今日 
} 
+0

Sembra che sia l'ultimo, no? – Mundi

+0

Penso, no.'String' non è' Array ' – rintaro

+0

Intendevo dire la penultima. È proprio come una variabile in-out. Forse la dicitura ** "che è passata" ** non è chiara. Potrebbe significare "questo è il modo in cui la funzione interpreterà questo argomento" (che penso sia inteso) o "questo è ciò che devi passare" (che credo non sia inteso qui). – Mundi

risposta

7

Questo sta funzionando bene Di una delle modifiche all'interoperabilità che il team Swift ha apportato dal lancio iniziale, hai ragione che sembra che non sia ancora entrato nella documentazione. String funziona dove è richiesto un UnsafePointer<UInt8> in modo che sia possibile chiamare le funzioni C che prevedono un parametro const char * senza molto lavoro aggiuntivo.

Guardate la funzione C strlen, definito in "shims.h":

size_t strlen(const char *s); 

In Swift viene attraverso come questo:

func strlen(s: UnsafePointer<Int8>) -> UInt 

che può essere chiamato con un String senza lavoro aggiuntivo:

let str = "Hi." 
strlen(str) 
// 3 

Guarda le revisioni di questa risposta per vedere h ow C-string interop è cambiato nel tempo: https://stackoverflow.com/a/24438698/59541

+0

Grazie! simpatico. Secondo le uscite di 'swiftc -emit-sil', in realtà crea temporaneamente' Array 'da' String.UTF8View.Generator'. Sembra * non * così veloce ... – rintaro

+0

Huh. Bene, l '"io" in SIL sta per intermedio, giusto? A seconda di come le stringhe sono effettivamente implementate nel runtime compilato (cosa succede se sono solo 'char *' sotto il cofano?), Che potrebbe essere un no-op. –

Problemi correlati