A NSInteger
é de 32 bits em plataformas de 32 bits e 64 bits em plataformas de 64 bits. Existe um NSLog
especificador que sempre corresponde ao tamanho de NSInteger
?
Configuração
- Xcode 3.2.5
- compilador llvm 1.6 (isso é importante; o gcc não faz isso)
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
ligadas
Isso está me causando um pouco de tristeza aqui:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}
Para código de 32 bits, preciso do %d
especificador. Mas se eu usar o %d
especificador, recebo um aviso ao compilar para 64 bits, sugerindo que eu o use %ld
.
Se eu usar %ld
o tamanho de 64 bits, ao compilar o código de 32 bits, recebo um aviso sugerindo que o use %d
.
Como faço para corrigir os dois avisos de uma só vez? Existe um especificador que eu possa usar que funcione também?
Isso também afeta [NSString stringWithFormat:]
e [[NSString alloc] initWithFormat:]
.
fonte
static inline NSIntToLong(NSInteger i) {return (long)i;}
. Isso evita desativar completamente a verificação de tipo (ou seja, se o tipo de i for alterado).static inline long NSIntToLong(NSInteger i) {return (long)i;}
NSLog(@"%@",@(mynsint));
stackoverflow.com/questions/20355439/…%zd
:Values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead
A resposta aceita é absolutamente razoável, está em conformidade com o padrão e está correta. O único problema é que ele não funciona mais, o que é completamente culpa da Apple.
O formato% zd é o formato padrão C / C ++ para size_t e ssize_t. Como o NSInteger e o NSUInteger, size_t e ssize_t são de 32 bits em um sistema de 32 bits e de 64 bits em um sistema de 64 bits. E é por isso que a impressão do NSInteger e do NSUInteger usando% zd funcionou.
No entanto, NSInteger e NSUInteger são definidos como "longos" em um sistema de 64 bits e como "int" em um sistema de 32 bits (que é de 64 vs 32 bits). Hoje, size_t é definido em "long" em todos os sistemas, que é do mesmo tamanho que o NSInteger (64 ou 32 bits), mas um tipo diferente. Os avisos da Apple foram alterados (portanto, não é permitido passar o tipo errado para printf, mesmo que tenha o número certo de bits) ou os tipos subjacentes para size_t e ssize_t foram alterados. Não sei qual, mas% zd parou de funcionar há algum tempo. Atualmente, não existe um formato que imprima o NSInteger sem aviso nos sistemas de 32 e 64 bits.
Portanto, a única coisa que você pode fazer infelizmente: Use% ld e converta seus valores de NSInteger para long, ou de NSUInteger para long assinatura.
Depois de não criar mais para 32 bits, você pode usar% ld, sem nenhuma conversão.
fonte
Os formatadores vêm da função de impressão padrão UNIX / POSIX. Use % lu por muito tempo não assinado ,% ld por muito tempo,% lld por muito tempo e % llu por muito tempo não assinado . Tente man printf no console, mas no Mac está incompleto. As páginas de manual do linux são mais explícitas http://www.manpages.info/linux/sprintf.3.html
Ambos os avisos podem ser corrigidos apenas pelo NSLog (@ "% lu", (long sem sinal) arg); combinado com um elenco, pois o código será compilado em 32 e 64 bits para iOS. Caso contrário, cada compilação cria um aviso separado.
fonte