Espacios de nombres
Variantes
Acciones

Conversiones aritméticas habituales

De cppreference.com
< cpp‎ | language
 
 
 
 

Muchos operadores binarios que esperan operandos de tipo aritmético o enumeración provocan conversiones y producen tipos de resultados de forma similar. El objetivo es producir un tipo común, que también es el tipo del resultado. Este patrón se denomina conversiones aritméticas habituales.

Contenido

[editar]Definición

Las conversiones aritméticas habituales se definen de la siguiente manera:

[editar]Etapa 1

Aplica conversión de l-valor a r-valor a ambos operandos, los pr-valores ​​resultantes se utilizan en lugar de los operandos originales para el resto del proceso.

[editar]Etapa 2

  • Si alguno de los operandos es de tipo enumeración, no se realizan conversiones; si el otro operando no tiene el mismo tipo, la expresión está mal formada.
  • De lo contrario, continúe con la siguiente etapa.
(desde C++11)

[editar]Etapa 3

  • Si alguno de los operandos es de tipo enumeración y el otro operando es de un tipo de enumeración diferente o un tipo de punto flotante, la expresión está mal formada.
  • De lo contrario, continúe con la siguiente etapa.
(desde C++26)

[editar]Etapa 4

  • Si ambos operandos tienen el mismo tipo, no se realizará ninguna conversión adicional.
  • De lo contrario, si uno de los operandos es de un tipo que no es de punto flotante, ese operando se convierte al tipo del otro operando.
  • De lo contrario, si los rangos de conversión de punto flotante de los tipos de los operandos están ordenados pero no son iguales, entonces el operando del tipo con el rango de conversión de punto flotante menor se convierte al tipo del otro operando.
  • De lo contrario, si los rangos de conversión de punto flotante de los tipos de los operandos son iguales, entonces el operando con el subrango de conversión de punto flotante menor se convierte al tipo del otro operando.
  • De lo contrario, la expresión está mal formada.
(desde C++23)
  • De lo contrario, ambos operandos son de tipo entero, se procede a la siguiente etapa.

[editar]Etapa 5

Ambos operandos se convierten a un tipo común C. Dados los tipos T1 y T2 como el tipo promocionado (según las reglas de promociones de enteros) de los operandos, se aplican las siguientes reglas para determinar C:

  • Si T1 y T2 son del mismo tipo, C es ese tipo.
  • De lo contrario, si T1 y T2 son ambos de tipo entero con signo o ambos de tipo entero sin signo, C es el tipo de rango de conversión de enteros mayor.
  • De lo contrario, un tipo entre T1 y T2 es un tipo de entero con signo S, el otro tipo es un tipo entero sin signo U. Se aplican las siguientes reglas:
  • Si el rango de conversión de enteros de U es mayor o igual que el rango de conversión de enteros de S, C es U.
  • De lo contrario, si S puede representar todos los valores de U, C es S.
  • De lo contrario, C es el tipo entero sin signo correspondiente a S.

Si un operando es de tipo enumeración y el otro operando es de un tipo enumeración diferente o un tipo de punto flotante, este comportamiento queda obsoleto.

(desde C++20)
(hasta C++26)

[editar]Rango de conversión de enteros

Cada tipo entero tiene un rango de conversión de enteros definido de la siguiente manera:

  • No hay dos tipos enteros con signo distintos de char y signedchar (si char tiene signo) que tengan el mismo rango, incluso si tienen la misma representación.
  • El rango de un tipo entero con signo es mayor que el rango de cualquier tipo entero con signo con un ancho menor.
  • Los rangos de los siguientes tipos enteros disminuyen en orden:
  • longlong
(desde C++11)
  • long
  • int
  • short
  • signedchar
  • El rango de cualquier tipo entero sin signo es igual al rango del tipo entero con signo correspondiente.
  • El rango de cualquier tipo entero estándar es mayor que el rango de cualquier tipo entero extendido con el mismo ancho.
(desde C++11)
  • El rango de bool es menor que el rango de todos los tipos enteros estándar.
  • Los rangos de los tipos de caracteres codificados (char, char8_t(desde C++20), char16_t, char32_t,(desde C++11) y wchar_t) son iguales a los rangos de sus tipos subyacentes, lo que significa:
  • El rango de char es igual al rango de signedchar y unsignedchar.
  • El rango de char8_t es igual al rango de unsignedchar.
(desde C++20)
(desde C++11)
  • El rango de wchar_t es igual al rango de su tipo subyacente definido por la implementación.
  • El rango de cualquier tipo entero con signo extendido en relación con otro tipo entero con signo extendido con el mismo ancho está definido por la implementación, pero aún está sujeto a las otras reglas para determinar el rango de conversión de enteros.
(desde C++11)
  • Para todos los tipos enteros T1, T2 y T3, si T1 tiene mayor rango que T2 y T2 tiene mayor rango que T3, entonces T1 tiene mayor rango que T3.

El rango de conversión de enteros también se utiliza en la definición de la promoción de enteros.

[editar]Rango y subrango de conversión de punto flotante

[editar]Rango de conversión de punto flotante

Cada tipo de punto flotante tiene un rango de conversión de punto flotante definido de la siguiente manera:

  • Los rangos de los tipos de punto flotante estándar disminuyen en orden:
    • longdouble
    • double
    • float
  • El rango de un tipo de punto flotante T es mayor que el rango de cualquier tipo de punto flotante cuyo conjunto de valores sea un subconjunto adecuado del conjunto de valores de T.
  • Dos tipos de punto flotante extendidos con el mismo conjunto de valores tienen rangos iguales.
  • Un tipo de punto flotante extendido con el mismo conjunto de valores que exactamente un tipo de punto flotante estándar sin calificación constvolatile tiene un rango igual al rango de ese tipo de punto flotante estándar.
  • Un tipo de punto flotante extendido con el mismo conjunto de valores que más de un tipo de punto flotante estándar sin calificación constvolatile tiene un rango igual al rango de double.
(desde C++23)

Subrango de conversión de punto flotante

Los tipos de punto flotante que tienen rangos de conversión de punto flotante iguales se ordenan por subrango de conversión de punto flotante. El subrango forma un orden total entre los tipos con rangos iguales.

Los tipos std::float16_t, std::float32_t, std::float64_t y std::float128_t (tipos de punto flotante de anchura fija) tienen un subrango de conversión mayor que cualquier tipo de punto flotante estándar con el mismo rango de conversión. De lo contrario, el orden del subrango de conversión está definido por la implementación.

(desde C++23)

[editar]Uso

El rango y subrango de conversión de punto flotante también se utilizan para

[editar]Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 1642 C++98 Las conversiones aritméticas habituales pueden involucrar l-valores. Aplica primero las conversiones de l-valor a r-valor.
CWG 2528 C++20 La comparación de tres vías entre unsignedchar
y unsignedint está mal formada debido a
la promoción de enteros intermedia.[1]
Determina el tipo común basado en los tipos
promocionados, sin promocionar realmente los operandos.[2]
CWG 2892 C++98 Cuando ambos operandos son del mismo tipo de punto flotante,
el significado de “no se necesita ninguna conversión adicional”
no estaba claro.
Se cambió a “no se realizará ninguna conversión adicional”.
  1. Antes de la resolución, unsignedchar se promueve a int al comienzo de la etapa 5, luego se convierte a unsignedint. Sin embargo, la última conversión es restrictiva, lo que hace que la comparación de tres vías esté mal formada.
  2. Después de la resolución, el tipo común sigue siendo unsignedint. La diferencia es que unsignedchar se convierte directamente en unsignedint sin la promoción de enteros intermedia. La conversión no es restrictiva y, por lo tanto, la comparación de tres vías está bien formada.
close