2013-04-18 12 views
128
NSInteger myInt = 1804809223; 
NSLog(@"%i", myInt); <==== 

Il codice precedente genera un errore:Perché una variabile NSInteger deve essere trasmessa su long se utilizzata come argomento di formato?

Values of type "NSInteger" should not be used as format arguments: add an explicit cast to 'long' instead. 

la correttezza NSLog messaggio è in realtà NSLog(@"%lg", (long) myInt); Perché devo convertire il valore intero di myInt a lungo se voglio il valore da visualizzare?

+1

@DanielLee, se si utilizza 'NSLog (@ "% ld", (lungo) myInt)', il Il cast 'long' è quello di farlo coincidere con il qualificatore' l' di '% ld', ma tutto ciò non è necessario poiché' NSLog (@ "% d", myInt); 'è sufficiente (dato che possiamo vedere che 'myInt' non è' long'. Bottom line, tu metti 'myInt' se usi un lungo qualificatore nella stringa di formato, ma non c'è bisogno di usare il qualificatore di formato stringa lungo o cast' long' qui. – Rob

+1

Apparentemente, non è vero che NSLog (@ "% i", myInt); è sufficiente perché visualizzerai il messaggio di errore come mostrato sopra. –

+1

@DanielLee Vedi il commento di Martin R. Hai postato la tua ricerca n con tag iOS (dove 'NSInteger' è _not_ lungo), ma sembra che tu stia compilando con OS X target (dove' NSInteger' _is_ 'long'). – Rob

risposta

182

Si ottiene questo avviso se si compila su OS X (64-bit), perché su quella piattaforma NSInteger è definito come long ed è un numero intero a 64 bit. Il formato %i, d'altra parte, è per int, che è 32 bit. Quindi il formato e il parametro attuale non corrispondono alla dimensione.

Poiché NSInteger è a 32 bit o 64 bit, a seconda della piattaforma, il compilatore consiglia di aggiungere un cast a long in genere.

Aggiornamento: Poiché iOS 7 ora supporta anche 64 bit, è possibile ottenere lo stesso avviso durante la compilazione di per iOS.

+0

Questo ha senso. Grazie. –

+0

Viene visualizzato questo errore su iOS 7. Poiché solo l'ultimo iPhone 5S è a 64 bit se lo imposto a lungo causerà problemi sui dispositivi a 32 bit più vecchi? –

+24

@BartSimpson: con un caso esplicito a "long", come in "NSLog (@"% ld ", (long) myInt)', funziona correttamente a 32-bit e 64-bit. –

34

Non è necessario eseguire il cast su nulla se gli specificatori di formato corrispondono ai tipi di dati. Vedere la risposta di Martin R per la quale i tipi nativi NSInteger sono definiti come.

Così su OS X a 64 bit, è possibile scrivere le sue dichiarazioni di log in questo modo:

NSLog(@"%ld", myInt); 

mentre su iOS si può scrivere:

NSLog(@"%d", myInt); 

e sarà tutto il lavoro senza calchi.

Un motivo per utilizzare cast comunque, almeno nel codice non UI, è che il buon codice tende a essere trasferito su piattaforme e se si esegue il cast delle variabili in modo esplicito si compilerà in modo pulito su 32 e 64 bit:

NSLog(@"%ld", (long)myInt); 

Questo aiuterà anche il tuo codice iOS in una transizione a 64 bit, dovrebbe mai venire su iOS. O quando iOS e OS X si fondono insieme lungo la linea.

E si noti che questo non vale solo per le istruzioni NSLog, che sono dopotutto strumenti di debug, ma anche per [NSString stringWithFormat:] e amici, che sono elementi legittimi del codice di produzione.

+1

Quindi, ora che questo hack è richiesto, è ancora meglio usare NSInteger? –

+0

@FullDecent È solo un problema nel codice interpretato come runtime, ad esempio le stringhe di formato. Il codice compilato Al sfrutta il typedef NSInteger. – Monolo

+0

È consigliabile utilizzare NSInteger, poiché esistono buoni motivi per definirne il modo in cui è definito. – gnasher729

21

Invece di passare un NSInteger a NSLog, basta passare un NSNumber. Questo aggirerà tutti i cast e sceglierà il giusto identificatore di formato stringa.

NSNumber foo = @9000; 
NSLog(@"foo: %@", foo); 
NSInteger bar = 9001; 
NSLog(@"bar: %@", @(bar)); 

Funziona anche per NSUIntegers senza doversi preoccupare di ciò. V. risposta alla NSInteger and NSUInteger in a mixed 64bit/32bit environment

+2

Suppongo che la risposta selezionata sia tecnicamente la migliore risposta alla domanda, ma se vuoi sapere come evitare ogni occorrenza e prevenire gli avvertimenti, trovo che questa sia la soluzione migliore. –

-1

OS X utilizza diversi tipi di dati-NSInteger, NSUInteger, CGFloat, e CFIndex-per fornire uno strumento coerente di valori che rappresentano in ambienti a 32 e 64 bit. In un ambiente a 32 bit, NSInteger e NSUInteger sono definiti rispettivamente come int e unsigned int. Negli ambienti a 64 bit, NSInteger e NSUInteger sono definiti come long e unsigned long, rispettivamente.Per evitare la necessità di utilizzare diversi identificatori di tipi di stile printf a seconda della piattaforma, è possibile utilizzare gli specificatori mostrati in this link per l'ambiente a 32 e 64 bit.

0

Mantiene avvertimento durante l'utilizzo NSLog(@"%ld", (long)myInt);, ma smette di avvertimento dopo la dichiarazione modifica long myInt = 1804809223; in iOS 10.

Problemi correlati