A NSInteger
tiene 32 bits en plataformas de 32 bits y 64 bits en plataformas de 64 bits. ¿Hay un NSLog
especificador que siempre coincida con el tamaño de NSInteger
?
Preparar
- Xcode 3.2.5
- Compilador llvm 1.6 (esto es importante; gcc no hace esto)
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF
encendido
Eso me está causando dolor aquí:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
@autoreleasepool {
NSInteger i = 0;
NSLog(@"%d", i);
}
return 0;
}
Para el código de 32 bits, necesito el %d
especificador. Pero si uso el %d
especificador, recibo una advertencia al compilar para 64 bits sugiriendo que use %ld
en su lugar.
Si uso %ld
para que coincida con el tamaño de 64 bits, cuando compilo para el código de 32 bits recibo una advertencia que sugiere que use %d
en su lugar.
¿Cómo soluciono ambas advertencias a la vez? ¿Hay algún especificador que pueda usar que funcione?
Esto también impacta [NSString stringWithFormat:]
y [[NSString alloc] initWithFormat:]
.
fuente
static inline NSIntToLong(NSInteger i) {return (long)i;}
. Esto evita deshabilitar la comprobación de tipo por completo (es decir, si el tipo de i cambia).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
La respuesta aceptada es absolutamente razonable, es conforme estándar y correcta. El único problema es que ya no funciona, lo cual es completamente culpa de Apple.
El formato% zd es el formato estándar C / C ++ para size_t y ssize_t. Al igual que NSInteger y NSUInteger, size_t y ssize_t son 32 bits en un sistema de 32 bits y 64 bits en un sistema de 64 bits. Y es por eso que la impresión de NSInteger y NSUInteger utilizando% zd funcionó.
Sin embargo, NSInteger y NSUInteger se definen como "largos" en un sistema de 64 bits y como "int" en un sistema de 32 bits (que es de 64 frente a 32 bits). Hoy, size_t se define en "largo" en todos los sistemas, que tiene el mismo tamaño que NSInteger (ya sea de 64 o 32 bits), pero de un tipo diferente. O las advertencias de Apple han cambiado (por lo que no permite pasar el tipo incorrecto a printf, aunque tenga el número correcto de bits), o los tipos subyacentes para size_t y ssize_t han cambiado. No sé cuál, pero% zd dejó de funcionar hace algún tiempo. Hoy no existe ningún formato que imprima NSInteger sin previo aviso en los sistemas de 32 y 64 bits.
Entonces, desafortunadamente, lo único que puede hacer es usar% ld y convertir sus valores de NSInteger a largo, o de NSUInteger a largo sin firmar.
Una vez que ya no construyes para 32 bits, puedes usar% ld, sin ningún tipo de conversión.
fuente
Los formateadores provienen de la función estándar printf de UNIX / POSIX. Use % lu para largos sin firmar ,% ld para largos,% lld para largos largos y % llu para largos sin firmar largos . Pruebe man printf en la consola, pero en Mac está incompleto. Las páginas de manual de Linux son más explícitas http://www.manpages.info/linux/sprintf.3.html
Ambas advertencias solo pueden ser reparadas por NSLog (@ "% lu", (sin signo largo) arg); combinado con un reparto, ya que el código se compilará en 32 y 64 bits para iOS. De lo contrario, cada compilación crea una advertencia por separado.
fuente