Uso ints sin firmar en todas partes, y no estoy seguro de si debería hacerlo. Esto puede ser desde columnas de identificación de clave primaria de la base de datos hasta contadores, etc. Si un número nunca debe ser negativo, siempre usaré un int sin signo.
Sin embargo, noto en el código de otros que nadie más parece hacer esto. ¿Hay algo crucial que estoy pasando por alto?
Editar: desde esta pregunta también he notado que en C, devolver valores negativos para errores es común en lugar de arrojar excepciones como en C ++.
c++
c
programming-practices
wting
fuente
fuente
for(unsigned int n = 10; n >= 0; n --)
(bucles infinitos)Respuestas:
Cuando los cálculos involucran tipos con y sin signo, así como diferentes tamaños, las reglas para la promoción de tipos pueden ser complejas y conducir a un comportamiento inesperado .
Creo que esta es la razón principal por la que Java omitió los tipos int sin signo.
fuente
int
Sin embargo, los tipos sin signo más pequeños que no plantearían tal dificultad (ya que cualquier cálculo promoveráint
); No tengo nada bueno que decir sobre la falta de un tipo de byte sin signo.Creo que Michael tiene un punto válido, pero en mi opinión, la razón por la que todos usan int todo el tiempo (especialmente en
for (int i = 0; i < max, i++
) es que lo aprendimos de esa manera. Cuando cada ejemplo en un libro de " cómo aprender programación " se usaint
en unfor
bucle, muy pocos cuestionarán esa práctica.La otra razón es que
int
es un 25% más corta que todosuint
, y todos somos flojos ... ;-)fuente
++
cuando se incrementan, a pesar de que su comportamiento particular rara vez es necesario e incluso podría dar lugar a cambios innecesarios sobre las copias si el índice de bucle es un iterador u otro tipo no fundamental (o el compilador es realmente denso) .Codificar información de rango en tipos es una buena cosa. Aplica el uso de números razonables en tiempo de compilación.
Muchas arquitecturas parecen tener instrucciones especializadas para manejar
int
->float
conversiones. La conversión deunsigned
puede ser más lenta (un poquito) .fuente
Mezclar tipos con y sin signo puede llevarte a un mundo de dolor. Y no puede usar todos los tipos sin signo porque encontrará cosas que tienen un rango válido que incluye números negativos o necesitan un valor para indicar un error y -1 es lo más natural. Entonces, el resultado neto es que muchos programadores usan todos los tipos de enteros con signo.
fuente
Para mí, los tipos tienen mucho que ver con la comunicación. Al usar explícitamente un int sin signo, me dice que los valores con signo no son valores válidos. Esto me permite agregar información al leer su código además del nombre de la variable. Idealmente, un tipo no anónimo me diría más, pero me da más información que si hubiera usado ints en todas partes.
Desafortunadamente, no todo el mundo es muy consciente de lo que comunica su código, y esa es probablemente la razón por la que ve entradas en todas partes, aunque los valores no estén firmados.
fuente
Utilizo
unsigned int
en C ++ para los índices de matriz, principalmente, y para cualquier contador que comience desde 0. Creo que es bueno decir explícitamente "esta variable no puede ser negativa".fuente
Debería preocuparse por esto cuando se trata de un número entero que realmente podría acercarse o exceder los límites de un int firmado. Como el máximo positivo de un entero de 32 bits es 2,147,483,647, debe usar un int sin signo si sabe que a) nunca será negativo yb) podría llegar a 2,147,483,648. En la mayoría de los casos, incluidas las claves y los contadores de la base de datos, nunca me acercaré a este tipo de números, así que no me preocupo por preocuparme si el bit de signo se usa para un valor numérico o para indicar el signo.
Yo diría: use int a menos que sepa que necesita un int sin firmar.
fuente
Es una compensación entre simplicidad y confiabilidad. Cuantos más errores se puedan detectar en el momento de la compilación, más confiable será el software. Diferentes personas y organizaciones están en diferentes puntos a lo largo de ese espectro.
Si alguna vez realiza una programación de alta confiabilidad en Ada, incluso utiliza diferentes tipos para variables como la distancia en pies frente a la distancia en metros, y el compilador lo marca si accidentalmente se asigna uno al otro. Eso es perfecto para programar un misil guiado, pero exagerado (juego de palabras) si está validando un formulario web. No hay necesariamente nada malo en ninguna de las formas, siempre y cuando cumpla con los requisitos.
fuente
Me inclino a estar de acuerdo con el razonamiento de Joel Etherton, pero llego a la conclusión opuesta. A mi modo de ver, incluso si sabe que es poco probable que los números se acerquen a los límites de un tipo con signo, si sabe que los números negativos no sucederán, entonces hay muy pocas razones para usar la variante con signo de un tipo.
Por la misma razón por la que, en algunas instancias seleccionadas, he usado
BIGINT
(entero de 64 bits) en lugar deINTEGER
(entero de 32 bits) en las tablas de SQL Server. La probabilidad de que los datos alcancen el límite de 32 bits dentro de un período de tiempo razonable es minúscula, pero si sucede, las consecuencias en algunas situaciones podrían ser bastante devastadoras. Solo asegúrate de mapear los tipos entre idiomas correctamente, o terminarás con una rareza interesante en el futuro ...Dicho esto, para algunas cosas, como los valores de clave primaria de la base de datos, con o sin signo, realmente no importa, porque a menos que esté reparando manualmente datos rotos o algo por el estilo, nunca estará tratando con el valor directamente; Es un identificador, nada más. En esos casos, la consistencia es probablemente más importante que la elección exacta de la firma. De lo contrario, terminará con algunas columnas de clave externa que están firmadas y otras que no están firmadas, sin ningún patrón aparente, o esa extraña rareza nuevamente.
fuente
Recomendaría que fuera de los contextos de almacenamiento de datos y de intercambio de datos con limitaciones de espacio, generalmente se usen tipos con signo. En la mayoría de los casos en los que un entero con signo de 32 bits sería demasiado pequeño, pero un valor sin signo de 32 bits sería suficiente por hoy, no pasará mucho tiempo antes de que el valor sin signo de 32 bits tampoco sea lo suficientemente grande.
Los tiempos principales en los que uno debe usar tipos sin signo son cuando uno está ensamblando múltiples valores en uno más grande (por ejemplo, convirtiendo cuatro bytes en un número de 32 bits) o descomponiendo valores más grandes en valores más pequeños (por ejemplo, almacenando un número de 32 bits como cuatro bytes) ), o cuando se tiene una cantidad que se espera que "se transfiera" periódicamente y se necesite tratar con ella (piense en un medidor de servicios residenciales; la mayoría de ellos tienen suficientes dígitos para asegurarse de que no se acumularán entre lecturas si se leen tres veces al año, pero no lo suficiente como para garantizar que no se vuelquen dentro de la vida útil del medidor). Los tipos sin signo a menudo tienen suficiente "rareza" que solo deberían usarse en casos donde su semántica es necesaria.
fuente
size_t
no está firmado yptrdiff_t
está firmado.Utilizo ints sin firmar para aclarar mi código y su intención. Una cosa que hago para protegerme de las conversiones implícitas inesperadas cuando hago aritmética con tipos con signo y sin signo es usar un short sin signo (generalmente 2 bytes) para mis variables sin signo. Esto es efectivo por un par de razones:
El principio general es que el tipo de sus variables sin signo debe tener un rango más bajo que el tipo de las variables con signo para garantizar la promoción al tipo con signo. Entonces no tendrá ningún comportamiento de desbordamiento inesperado. Obviamente, no puede garantizar esto todo el tiempo, pero (la mayoría de las veces) es factible garantizarlo.
Por ejemplo, recientemente tuve un bucle for algo como esto:
El literal '2' es de tipo int. Si yo fuera un unsigned int en lugar de un unsigned short, entonces en la sub-expresión (i-2), 2 se promocionaría a unsigned int (dado que unsigned int tiene una prioridad más alta que la firma int). Si i = 0, entonces la sub-expresión es igual a (0u-2u) = algún valor masivo debido al desbordamiento. La misma idea con i = 1. Sin embargo, dado que i es un corto sin signo, se promociona al mismo tipo que el literal '2', que está firmado int, y todo funciona bien.
Para mayor seguridad: en el raro caso en el que la arquitectura que está implementando hace que int sea de 2 bytes, esto podría hacer que ambos operandos en la expresión aritmética se promocionen a unsigned int en el caso en que la variable corta sin signo no encaje en el int de 2 bytes firmado, el último de los cuales tiene un valor máximo de 32,767 <65,535. (Consulte https://stackoverflow.com/questions/17832815/c-implicit-conversion-signed-unsigned para obtener más detalles). Para protegerse de esto, simplemente puede agregar un static_assert a su programa de la siguiente manera:
y no se compilará en arquitecturas donde int es de 2 bytes.
fuente