language agnostic - ¿Cuándo usar valores sin signo sobre los firmados?
language-agnostic types (5)
Creo que si su caso de negocios dicta que un número negativo no es válido, desearía que se muestre o arroje un error.
Con eso en mente, recientemente descubrí enteros sin firmar mientras trabajaba en un proyecto que procesaba datos en un archivo binario y almacenaba los datos en una base de datos. Estaba "corrompiendo" los datos binarios a propósito y terminé obteniendo valores negativos en lugar de un error esperado. Descubrí que aunque el valor convertido, el valor no era válido para mi caso de negocio.
Mi programa no falló y terminé recibiendo datos incorrectos en la base de datos. Hubiera sido mejor si hubiera usado uint
y hubiera fallado el programa.
¿Cuándo es apropiado usar una variable sin signo sobre una con signo? ¿Qué pasa en un bucle for
?
Escucho muchas opiniones sobre esto y quería ver si había algo parecido a un consenso.
for (unsigned int i = 0; i < someThing.length(); i++) {
SomeThing var = someThing.at(i);
// You get the idea.
}
Sé que Java no tiene valores sin signo, y esa debe haber sido una decisión consciente por parte de Sun Microsystems .
En su ejemplo anterior, cuando ''i'' siempre será positivo y un rango más alto sería beneficioso, sin signo sería útil. Como si usara declaraciones ''declarar'', como:
#declare BIT1 (unsigned int 1)
#declare BIT32 (unsigned int reallybignumber)
Especialmente cuando estos valores nunca cambiarán.
Sin embargo, si está haciendo un programa de contabilidad donde las personas son irresponsables con su dinero y están constantemente en números rojos, definitivamente querrá usar ''firmado''.
Sin embargo, estoy de acuerdo con Saint en que una buena regla general es usar firmado, que C en realidad es el predeterminado, por lo que está cubierto.
Los compiladores de C y C ++ generarán una advertencia cuando compare tipos con y sin signo; en su código de ejemplo, no puede hacer que su variable de bucle no esté firmada y que el compilador genere código sin advertencias (suponiendo que dichas advertencias estén activadas).
Naturalmente, estás compilando con advertencias al revés, ¿verdad?
Y, ¿ha considerado compilar con "tratar las advertencias como errores" para ir un paso más allá?
La desventaja de usar números con signo es que existe la tentación de sobrecargarlos para que, por ejemplo, los valores 0-> n sean la selección del menú, y -1 significa que no hay nada seleccionado, en lugar de crear una clase que tenga dos variables, una para indicar si algo está seleccionado y otro para almacenar cuál es esa selección. Antes de que te des cuenta, estás probando uno negativo por todas partes y el compilador se queja de cómo quieres comparar la selección del menú con el número de selecciones del menú que tienes, pero eso es peligroso porque son diferentes tipos . Entonces no hagas eso.
Me alegré de encontrar una buena conversación sobre este tema, ya que realmente no lo había pensado mucho antes.
En resumen, firmar es una buena opción general, incluso cuando está seguro de que todos los números son positivos, si va a hacer aritmética en la variable (como en un caso típico de bucle).
Si vas a hacer cosas bit a bit como máscaras, sin signo comienza a tener más sentido. O, si estás desesperado por obtener ese rango positivo adicional aprovechando el bit de signo.
Personalmente, me gusta firmar porque no confío en mí mismo para mantener la coherencia y evitar mezclar los dos tipos (como advierte el artículo).
size_t
suele ser una buena opción para esto, o size_type
si está utilizando una clase STL.