¿Por qué una variable NSInteger tiene que ser convertida a long cuando se usa como argumento de formato?


NSInteger myInt = 1804809223;
NSLog(@"%i", myInt); <==== 

El código anterior produce un error:

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

El mensaje NSLog correcto es en realidad NSLog(@"%lg", (long) myInt); ¿Por qué tengo que convertir el valor entero de myInt a long si quiero que se muestre el valor?

Author: Tony Adams, 2013-04-18

5 answers

Recibe esta advertencia si compila en OS X (64 bits), porque en esa plataforma NSInteger se define como long y es un entero de 64 bits. El formato %i, por otro lado, es para int, que es de 32 bits. Por lo tanto, el formato y el parámetro real no coinciden en tamaño.

Dado que NSInteger es de 32 bits o 64 bits, dependiendo de la plataforma, el compilador recomienda para agregar un molde a long generalmente.

Actualización: Dado que iOS 7 es compatible con 64 bits ahora también, puede obtener la misma advertencia al compilar para iOS.

 185
Author: Martin R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-10 09:24:10

No tiene que convertir a nada si sus especificadores de formato coinciden con sus tipos de datos. Vea la respuesta de Martin R para los tipos nativos NSInteger que se define como.

Así que en OS X de 64 bits, puede escribir sus declaraciones de registro como esta:

NSLog(@"%ld",  myInt); 

Mientras que en iOS se puede escribir:

NSLog(@"%d",  myInt); 

Y todo funcionará sin moldes.

Una razón para usar casts de todos modos, al menos en el código que no es de interfaz de usuario, es que el buen código tiende a ser portado a través de plataformas, y si explícitamente compilará limpiamente tanto en 32 como en 64 bits:

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

Esto también ayudará a su código de iOS en una transición a 64 bits, si alguna vez llega a iOS. O cuando iOS y OS X se fusionan en la línea.

Y observe que esto va no solo para las sentencias NSLog, que son solo ayudas de depuración después de todo, sino también para [NSString stringWithFormat:] y amigos, que son elementos legítimos del código de producción.

 36
Author: Monolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-18 07:29:22

En lugar de pasar un NSInteger a NSLog, simplemente pase un NSNumber. Esto evitará todos los moldes y elegirá el especificador de formato de cadena correcto.

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

También funciona para NSUIntegers sin tener que preocuparse por eso. Ver respuesta a NSInteger y NSUInteger en un entorno mixto de 64 bits / 32 bits

 22
Author: orkoden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:27

Mantiene la advertencia mientras se usa NSLog(@"%ld", (long)myInt);, pero deja de advertir después de cambiar la declaración a long myInt = 1804809223; en iOS 10.

 0
Author: Yao Li,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 17:44:48

OS X utiliza varios tipos de datos-NSInteger, NSUInteger,CGFloat y CFIndex-para proporcionar un medio consistente de representar valores en entornos de 32 y 64 bits. En un entorno de 32 bits, NSInteger y NSUInteger se definen como int y unsigned int, respectivamente. En entornos de 64 bits, NSInteger y NSUInteger se definen como long y unsigned long, respectivamente. Para evitar la necesidad de utilizar diferentes especificadores de tipo printf en función de la plataforma, puede utilizar los especificadores que se muestran en este enlace para el entorno de 32 bits y 64 bits.

 -2
Author: Saheb Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-17 12:20:25