¿Cuándo es apropiado usar una variable sin firmar sobre una firmada? ¿Y en un for
bucle?
Escuché 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 firmar, y esa debe haber sido una decisión consciente por parte de Sun Microsystems .
language-agnostic
types
Bernardo
fuente
fuente
Respuestas:
Me alegré de encontrar una buena conversación sobre este tema, ya que no lo había pensado mucho antes.
En resumen, con signo es una buena opción general, incluso cuando está completamente 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 for).
Si va a hacer cosas bit a bit como máscaras, sin firmar comienza a tener más sentido. O, si está 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).
fuente
unsigned
es muy superior para detectar desbordamientos en entradas que no son de confianza. Desafortunadamente, las "respuestas" propuestas al rompecabezas no son tan buenas. La mía es quetemplate<size_t limit> bool range_check_sum( unsigned a, unsigned b ) { return (a < limit) && (b < limit - a); }
si alguien tiene una respuesta igualmente simple y directa usando tipos firmados, me encantaría verla.En su ejemplo anterior, cuando 'i' siempre será positivo y un rango más alto sería beneficioso, sin firmar sería útil. Como si estuviera usando declaraciones 'declarar', como:
Especialmente cuando estos valores nunca cambiarán.
Sin embargo, si está realizando un programa de contabilidad en el que 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.
fuente
Creo que si su caso de negocios dicta que un número negativo no es válido, le gustaría que se mostrara o arrojara un error.
Con eso en mente, recientemente descubrí los números enteros sin firmar mientras trabajaba en un proyecto que procesaba datos en un archivo binario y los almacenaba en una base de datos. A propósito, estaba "corrompiendo" los datos binarios y terminé obteniendo valores negativos en lugar de un error esperado. Descubrí que aunque el valor se convirtió, el valor no era válido para mi caso comercial.
Mi programa no falló y terminé obteniendo datos incorrectos en la base de datos. Hubiera sido mejor si lo hubiera usado
uint
y hubiera fallado el programa.fuente
Los compiladores de C y C ++ generarán una advertencia cuando compare tipos firmados y no firmados; en su código de ejemplo, no podría 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á compilando con advertencias al máximo, ¿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 la cantidad de selecciones de menú que tienes, pero eso es peligroso porque son de diferentes tipos. . Así que no hagas eso.
fuente
size_t
a menudo es una buena opción para esto, osize_type
si está utilizando una clase STL.fuente
size_type
miembro para recuentos de elementos, no solo bytes. Debería usarse en lugar destd::size_t
donde esté disponible, pero es inexacto dar a entender que cualquier cosa que comience consize_t
solo puede significar bytes.