Conversión de entero negativo a entero más grande sin signo

I've encountered code that performs the following conversion:

static_cast<unsigned long>(-1)

As far as I can tell, the C++ standard defines what happens when converting a signed integer value to an unsigned integral type (see: ¿Qué sucede si asigno un valor negativo a una variable sin signo?).

The concern I have in the above code is that the source and destination types may be different sizes and whether or not this has an impact on the result. Would the compiler enlarge the source value type before casting? Would it instead cast to an unsigned integer of the same size and then enlarge that? Or perhaps something else?

To clarify with code,

int nInt = -1;
long nLong = -1; // assume sizeof(long) > sizeof(int)

unsigned long res1 = static_cast<unsigned long>(nInt)
unsigned long res2 = static_cast<unsigned long>(nLong);

assert(res1 == res2); // ???

Basically, should I be worrying about writing code like

static_cast<unsigned long>(-1L)

Más de

static_cast<unsigned long>(-1)

preguntado el 14 de febrero de 14 a las 01:02

The noun is "integer". (integral is also a noun... in calculus, not C++) -

Ack! You're right. Too much Haskell programming... -

2 Respuestas

From the C++11 standard, 4.7 "Integral conversions", para 2:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type).

In other words, when converting to an unsigned integer, only the value of the input matters, not its type. Converting -1 to an n-bit unsigned integer will always give you 2n-1, regardless of which integer type the -1 started as.

Respondido 14 Feb 14, 01:02

This is why I'm no good at using specs. That sentence makes little sense to me, mostly because it hinges on the definition of "congruent". Is that defined elsewhere in the spec? Because the English definition doesn't really help. I could just as easily say that (uint32_t)-1 should be 0x00000001 because -1 is more similar to 1 than it is to 4294967295. If you use the geometric definition of "identical in form; coinciding exactly when superimposed" then there isn't an unsigned number that will ever match -1. - apestoso

It's using the mathematical definition of congruent: two numbers are congruent modulo N if they both leave the same remainder when divided by N. - Ross Smith

This is a good question and the borrador del estándar C ++ on this section 4.7 Conversiones integrales Que dice:

Si el tipo de destino no tiene signo, el valor resultante es el menor entero sin signo congruente con el entero de origen (módulo 2n where n is the number of bits used to represent the unsigned type).[...]

is not the most straight forward to interpret, in this case I would go back to the proyecto de norma C99 Que dice:

De lo contrario, si el nuevo tipo no tiene signo, el valor se convierte sumando o restando 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

donde nota al pie 49 helpfully says:

The rules describe arithmetic on the mathematical value, not the value of a given type of expression.

This is more straight forward and clearly gives us the result as -1 + MAX + 1 cual es MAX, regardless of what type of the operand is.

Respondido el 30 de diciembre de 14 a las 09:12

The C++ version seems more clearly specified to me ! - MM

@MattMcNabb I did not say more clearly specified, I said straight forward or more accessible to a wider range of people. It is better specified in C++. - Shafik Yaghmour

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.