2011-12-05 17 views
10

es, por ejemplo¿Es -1u válido C++?

size_t x = -1u; 

if (x == -1u) 
    ... 

válida?

Si esto es válido, evitaría una advertencia. por supuesto en un sistema de 32 bits x debe ser 0xffffffff y en un sistema de 0 bit de 64 bits debe ser 0xffffffffffffffff.

-Jochen

+7

Literales siempre son no negativos. Esto se analiza como '- (1u)'. –

+0

@KerrekSB ¿eso hace la diferencia aquí? –

+0

Bueno, hace que el resultado se firme, por lo que se pierde el objetivo de la U. – StilesCrisis

Respuesta

6

1u tiene el tipo unsigned int. Esto se niega utilizando el operador único -. El comportamiento es el siguiente:

El negativo de una cantidad sin signo se calcula restando su valor desde 2 n, donde n es el número de bits en el operando promovido (C++ 11 5.3.1/8).

-1u es por lo tanto garantizado para darle el mayor valor representable por unsigned int.

Para obtener el mayor valor representable por un tipo arbitrario sin signo, puede convertir -1 en ese tipo. Por ejemplo, para std::size_t, considere static_cast<std::size_t>(-1).

0

Si bien esto es técnicamente código válido, que está en función de la conducta depende de la implementación: el manejo de desbordamiento de convertir un número negativo para firmar. Sin embargo, si necesita comparar significativamente un tamaño_t con -1 porque las llamadas API que está utilizando lo requieren, el sistema ya está estropeado, pero es probable que su código funcione porque tendrían que hacer lo mismo del otro lado. de la API.

+0

No soy un experto en C++, pero dudo que la conversión del tipo entero con signo al tipo entero sin signo esté definido en la implementación en C++, porque está definido en C99. –

+0

Está bien definido. Creo que es algo así como 'x% 2^32' para 32 bits. – Pubby

+1

Ningún número negativo se convierte en unsigned. '1u' es un número positivo de tipo' unsigned int', y ese número positivo se niega utilizando el operador unario '-'. –

5

Siempre he usado ~ 0U con el propósito de "unsigned, all bit on".

+4

... que no funcionará para un 'tamaño_t' de 64 bits. –

+1

SIZE_MAX es probablemente mejor en ese caso, o ~ 0ULL como una alternativa. – StilesCrisis

+0

Sin embargo, tenga cuidado de no escribir '~ 0'. El 'U' aquí es muy importante. Para más información, consulte http://stackoverflow.com/questions/809227/is-it-safe-to-use-1-to-set-all-bits-to-true –

1

El comportamiento dependiente de la implementación del compilador es molesto. Usted debe ser capaz de hacer esto, sin embargo:

size_t x = 0; 
x--; 

if ((x+1) == 0) 
+0

Este es un comportamiento indefinido. El código que publicó no es. – Pubby

+0

@Pubby: ¿Qué en esta respuesta crees que exhibe un comportamiento indefinido? –

+1

Pubby, ¿dónde ves UB? Los tipos sin firmar (y size_t es un tipo sin firmar) tienen un comportamiento bien definido en el desbordamiento, se envuelven. (El desbordamiento firmado es UB). – AProgrammer

0

Esto es probablemente lo que quiere:

size_t x = -1ull; 

if (x == -((size_t)-1ull)) 
    ... 

x se establecerá en el entero más grande posible, que puede no ser todos los bits. Use ~ 0 para eso.

+0

Muchos años a partir de ahora cuando 'size_t' es más ancho que' unsigned long long', 'size_t x = -1ull;' (quizás 'size_t' como un typedef a un ancho' uintmax_t') no podrá ser inicializado 'x' con el valor máximo 'size_t x = SIZE_MAX;' seguirá funcionando. – chux