2010-03-31 23 views
28

¿Alguien tiene la experiencia para explicar cuándo usar NSUInteger y cuándo usar NSInteger?NSUEntero vs NSInteger, int vs unsigned, y casos similares

He visto que los métodos Cocoa devuelven NSInteger incluso en casos en que el valor devuelto siempre estará sin firmar.

¿Cuál es el motivo fundamental? ¿Está NSInteger o int estrictamente limitado a si queremos representar un valor negativo?

De NSObjCRuntime.h:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64 
typedef long NSInteger; 
typedef unsigned long NSUInteger; 
#else 
typedef int NSInteger; 
typedef unsigned int NSUInteger; 
#endif 

Respuesta

30

También debe ser consciente de las reglas de conversión de enteros cuando se trata de NSUInteger vs NSInteger:

El siguiente fragmento de ejemplo devuelve 0 (falso), aunque se espera también para imprimir 1 (verdadero):

NSInteger si = -1; 
NSUInteger ui = 1; 
printf("%d\n", si < ui); 

la razón es que el [si] variable se va a convertir implícitamente a un unsigned int!

Ver CERT's Secure Coding site para una discusión en profundidad en torno a estos 'problemas' y cómo resolverlos.

+0

Este es el nuevo enlace https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules –

7

Si el método tiene un rango de salida adecuadamente restringido, que también podría utilizar NSInteger ya que es más fácil de escribir. Como dices, si necesitas devolver números negativos, NSInteger es el único juego de la ciudad; Solo usaría NSUInteger si tuviera que devolver realmente números grandes por algún motivo.

+1

Para los números aún más grandes, utilice NSDecimalNumber de 38 plazas de base 10 de precisión. – codewarrior

+0

+1, @codewarrior, solo si puedes superar las clases. –

+7

Voy por el otro lado: uso NSUInteger en todo momento, excepto cuando necesito números negativos.Además, te refieres a objetos, no a clases; hay muy pocas razones para aprobar clases, e incluso menos razones para aprobar específicamente la clase NSDecimalNumber. –

5

No sé acerca de cacao en concreto, pero por lo general la única desventaja de enteros con signo es por lo general tienen la mitad del valor máximo como un entero sin signo. Tales como alrededor de 2 mil millones en lugar de 4 mil millones para sistemas de 32 bits. En general, esta no es una gran diferencia, ya que si está lidiando con valores cercanos a los 2.000 millones, probablemente estaría igual de preocupado por un máximo de 4 mil millones en el mismo caso, ya que todavía está cerca de un desbordamiento con solo un multiplicación de 2 o 3.

Los enteros con signo suelen preferirse porque la flexibilidad adicional y el hecho de que un entero con signo se puede usar en casi todos los escenarios, puede ser un entero sin signo más todos los escenarios adicionales que no es necesario.

Sin firmar puede ser preferible si desea aplicar valores positivos solamente.

+0

Agregué las definiciones de NSInteger y NSUInteger. –

+4

Los enteros con signo se utilizan a veces incluso cuando el rango normal es positivo si desea poder inicializar una variable a un valor "no válido" como -1. – progrmr

+3

Curiosamente, Swift, el sustituto del Objetivo C, dice que siempre use números con signos cuando sea posible. * From the docs *: Use UInt solo cuando necesite específicamente un tipo entero sin signo con el mismo tamaño que el tamaño de palabra nativo de la plataforma. Si este no es el caso, se prefiere Int, incluso cuando se sabe que los valores almacenados son no negativos. Un uso constante de Int para valores enteros ayuda a la interoperabilidad del código, evita la necesidad de convertir entre diferentes tipos de números y hace coincidir la inferencia del tipo entero, como se describe en Seguridad de tipos e Inferencia de tipos. – Skotch

17

De forma predeterminada, se supone que un entero está firmado. En otras palabras, el compilador supone que se solicitará a una variable entera que almacene un número negativo o positivo. Esto limita la extensión que el alcance puede alcanzar en cualquier dirección. Por ejemplo, un int int. De 32 bits tiene un rango de 4.294.967.295. En la práctica, dado que el valor puede ser positivo o negativo, el rango es de -2,147,483,648 a +2,147,483,647. Si sabemos que nunca se solicitará a una variable que almacene un valor negativo, podemos declararlo como no firmado, extendiendo así el rango (positivo) de 0 a +4,294,967,295. Entonces, diría que está bien usar NSInteger cuando sabes que tienes un rango de salida restringido. Yo personalmente uso NSUInteger si necesitaba volver realmente grandes sólo números positivos

+0

Buena respuesta y qué Necesitaba saber :) – mAc

+0

¿Qué sucede si quiero almacenar -4,294,967,295? No puedo usar NSInteger entonces? – Nil

+0

@Nil largo largo int: -9,223,372,036,854,775,807 a 9,223,372,036,854,775,807 largo sin signo largo int: 0 a 18,446,744,073,709,551,615. Una cantidad bastante grande para tenerlo en su cuenta: D –