2009-11-03 8 views
10

El otro día, I came across este constructo:¿Qué tan portátil está lanzando -1 a un tipo sin firmar?

static_cast<size_type>(-1) 

en algún ejemplo código C++, que es probable (dependiendo de los detalles de donde size_type es de) a ser equivalente a la siguiente C:

(size_t)(-1) 

Según tengo entendido, funciona basado en el hecho de que la representación de -1 en dos aritmética de complemento es 11111...1, para tantos bits como usted tenga, por lo que esta es una manera rápida de obtener el valor máximo que un tipo sin signo como size_t puede contener. Sin embargo, tengo entendido que C no garantiza que se utilizará el complemento a dos; si la implementación de C usa el complemento de uno, este será 1 menos que el valor máximo, y si usa la magnitud con signo, será un poco más de la mitad del valor máximo.

¿Hay alguna arruga que me falta que asegure que esto funciona bien independientemente de la representación de los enteros con signo que se utilizan? ¿Difiere entre C y C++ (muchas cosas sorprendentes lo hacen)?

+3

Si quiere estar seguro, siempre hay 'std :: numeric_limits :: max()'. – UncleBens

+0

Creo que situaciones como esta tienen static_cast y reinterpret_cast en el lenguaje: static_cast puede proporcionarle algo predecible (y por lo tanto útil) pero que podría tener una implementación más lenta en algunas plataformas, mientras que reinterpret_cast puede eliminar cualquier garantía. – Kylotan

+3

Esto es en mi humilde opinión la mejor manera de obtener un número de todos los bits.Las opciones que usan '~ 0U' también funcionan (y si olvida agregar' U' y do '~ 0' puede terminar con todos los bits 0, por ejemplo) - pero usando' -1' fundido al tipo 'unsigned' , siempre funciona independientemente del tipo. Por lo tanto, no tiene que preocuparse por usar 'ULL' o para convertirlo en' unsigned short' primero; puede usar '-1' y asignarlo :) Vea también http://stackoverflow.com/questions/809227/ is-it-safe-to-use-1-to-set-all-bits-to-true –

Respuesta

19

Los requisitos de la aritmética sin signo garantizan que la conversión -1 a un tipo sin signo producirá el mayor número posible para el tipo de destino. C99, §6.2.5/9: "... un resultado que no puede ser representado por el tipo de entero sin signo resultante es un módulo reducido el número que es uno mayor que el valor más grande que puede ser representado por el tipo resultante".

Esto es lo mismo en C y C++ (en el estándar de C++, la fraseología similar se encuentra en la nota al pie 41 - no es normativa, pero está explicando otra redacción).

+6

Para C++, la redacción normativa es '4.7/2 '. –

+0

Gracias! Esa es exactamente la arruga que me preguntaba – Pillsy

14

estar en un lado "seguro" y hacerlo "derecho" (C++) manera, vale la pena mirar STL: valor

std::numeric_limits<size_t>::max() 
+3

El único inconveniente de esto es que el valor no es una expresión constante. Puede hacer 'integral_constant ', pero 'integral_constant :: max()>' no funciona :( –

2

Si usted está mirando para conseguir el máximo (o mínimo) de cierto tipo de forma portátil, es mejor utilizar la clase estándar numeric_limits de la siguiente manera.

#include <limits> 

size_type max = std::numeric_limits<size_type>::max() 
size_type min = std::numeric_limits<size_type>::min() 

sospecho que algunas implementaciones de estas funciones pueden usar la conversión que usted describe como la forma de plataforma óptima para llegar al mínimo/máximo.

5

"Según tengo entendido, funciona basado en el hecho de que la representación de -1 en dos aritmética de complemento es ...".

No, no se basa en absoluto en ese hecho. Se basa en el requisito estándar, que los valores chamuscados convertidos a tipo sin signo de N bits tienen que producir un valor sin signo, que es "igual" al módulo firmado original 2^N.

Tiene que funcionar de esa manera, independientemente de la representación firmada utilizada por la implementación. En el caso del complemento a 2, funciona de esa manera por sí mismo, pero para otras representaciones el compilador tendrá que hacer el trabajo adicional para cumplir con el requisito estándar.

+0

Uh ... para ser justos: el estándar está escrito de la misma manera que es posible permitir implementaciones sencillas en CPU que hacen aritmética de complemento de 2. Sin duda no es ** incorrecto ** para invocar el complemento de 2 en una explicación. Existen estándares de lenguaje para atender las necesidades del hardware y el usuario, y no al revés. –

+0

Estoy de acuerdo con la parte de "servir a los usuarios". las necesidades del hardware "? ... No. – AnT

+0

He bajado las respuestas antes, cuando leo en ellas" el valor es 'UINT_MAX' porque en el complemento a dos' '-1' es todo en uno". simplemente lo tenía al revés. r, renunciaré a esta respuesta. –

Cuestiones relacionadas