c++ - manipulation - Usando-1 como valor de indicador para tipos sin signo(size_t)
manipulate bits in c++ (3)
Estaba usando -1 como valor de indicador para una función cuyo tipo de devolución es size_t (un tipo sin signo).
Al principio no me di cuenta, particularmente porque no estaba causando ningún error en mi código (lo estaba comprobando con x == -1, no x <0).
¿Hay alguna razón sutil para no dejarlo como está? ¿Cuándo podría esto comportarse inesperadamente? Es esto comúnmente usado?
ptrdiff_t es menos común, tarda más en escribir y, de todos modos, no es realmente el tipo apropiado, ya que la función devuelve un índice en una matriz.
Después de tratar de pensar en qué podría salir mal, me di cuenta de que existe el peligro de que la función de llamada implícitamente arroje el valor de retorno a un tipo más grande (es decir, unsigned int a unsigned long long). Luego verificando si ese valor == -1 será falso.
La opción más segura es usar explícitamente size_t.max como valor centinela. Siempre me siento incómodo con el cambio entre tipos firmados y no firmados. A veces pienso que el enfoque más razonable es simplemente hacer que todo se firme (como hace Java).
La advertencia obvia se encuentra en el caso de un conjunto de elementos con un tamaño igual al tamaño más grande posible. La posibilidad y la usabilidad de que esto suceda en la práctica y que realmente sean la causa de su problema en ese momento son insignificantes.
Si observa la clase C ++ std::string
, notará que el miembro static std::string::npos
se define exactamente como -1
convertido a std::string::size_type
(que en realidad es std::size_t
Eso le da a esta "técnica" un sentido de precedencia, lo que le permite completar The Principle of Least Surprise ™, que siempre es un Good Thing®.
Ahora, usar -1
directamente en una comparación como esa es buscar problemas. Debería, como en el caso de std::string
, asegurarse de que haya un nombre accesible para este valor que garantice su significado especial. desafortunadamente, el sistema de tipo C ++ no es lo suficientemente estricto como para evitar que un usuario se pegue un tiro en el pie, pero al menos un usuario que se adhiere a las mejores prácticas documentadas no pensará en hacer las cosas de manera diferente.
-1
siempre convertirá al valor máximo sin signo, esto se debe a la sección 4.7
Conversiones integrales :
Si el tipo de destino no está firmado, el valor resultante es el entero menos sin signo congruente con el entero de origen (módulo 2n donde n es el número de bits utilizados para representar el tipo sin signo). [Nota: en una representación de complemento de dos, esta conversión es conceptual y no hay cambios en el patrón de bits (si no hay truncamiento). -finalizar nota]
La misma cotización para C99 sería de 6.3.1.3
:
De lo contrario, si el nuevo tipo no está firmado, el valor se convierte al agregar o restar repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo. 49)
Así que terminamos con:
-1 + (UMAX + 1)
cual es:
UMAX