Reglas implícitas de conversión de tipos en operadores C++


Quiero ser mejor acerca de saber cuándo debo lanzar. Cuáles son las reglas implícitas de conversión de tipos en C++ al sumar, multiplicar, etc. Por ejemplo,

int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?

Etcétera...

¿Se evaluará siempre la expresión como el tipo más preciso? ¿Las reglas difieren para Java? Por favor corríjame si he redactado esta pregunta incorrectamente.

Author: Matt Montag, 2011-04-06

9 answers

En C++ los operadores (para tipos POD) siempre actúan sobre objetos del mismo tipo.
Por lo tanto, si no son los mismos se promoverán para que coincida con el otro.
El tipo del resultado de la operación es el mismo que los operandos (después de la conversión).

If either is      long          double the other is promoted to      long          double
If either is                    double the other is promoted to                    double
If either is                    float  the other is promoted to                    float
If either is long long unsigned int    the other is promoted to long long unsigned int
If either is long long          int    the other is promoted to long long          int
If either is long      unsigned int    the other is promoted to long      unsigned int
If either is long               int    the other is promoted to long               int
If either is           unsigned int    the other is promoted to           unsigned int
If either is                    int    the other is promoted to                    int
Both operands are promoted to int

Nota. El tamaño mínimo de las operaciones es int. Así que short/char se promocionan a int antes de que se realice la operación.

En todas sus expresiones el int se promueve a un float antes de que se realice la operación. El resultado de la operación es un float.

int + float =>  float + float = float
int * float =>  float * float = float
float * int =>  float * float = float
int / float =>  float / float = float
float / int =>  float / float = float
int / int                     = int
int ^ float =>  <compiler error>
 179
Author: Martin York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-27 23:13:45

Las operaciones aritméticas que implican float dan como resultado float.

int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int

Para una respuesta más detallada. Mira lo que dice la sección §5/9 del estándar C++

Muchos operadores binarios que esperan operandos de aritmética o enumeración tipo causa conversiones y rendimiento tipos de resultados de una manera similar. El el propósito es producir un tipo común, , que es también el tipo del resultado.

Este patrón se llama el habitual conversiones aritméticas, que ser se define como sigue:

- Si cualquiera de los operando es de tipo long doble, el otro se convertirá por el doble largo.

- De lo contrario, si operando es doble, el otro será convierte a double.

- De lo contrario, si cualquiera de los operando es float, el otro se convertirá en flotador.

- De lo contrario, las promociones integrales (4.5) se llevará a cabo en ambos operandos.54)

- Entonces, si cualquiera de los operando no está firmado largo será el otro convertido a largo sin signo.

- De lo contrario, si un operando es un int y el otro int sin signo, entonces si un int largo puede representar todos los valores de un int sin signo, el unsigned int shall be converted to a long int; de lo contrario ambos operandos se convertirá a largo sin signo int.

- De lo contrario, si cualquiera de los operando es largo, el otro se convertirá en largo.

- De lo contrario, si cualquiera de los operando no está firmado, el otro será convertido a sin signo.

[Nota: de lo contrario, el único caso restante es que ambos operandos son int]

 28
Author: Nawaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 07:56:13

Dado que las otras respuestas no hablan de las reglas en C++11, aquí hay una. Del estándar C++11 (borrador n3337) §5/9:

Este patrón se llama conversiones aritméticas usuales , que se definen de la siguiente manera:

- Si uno de los operando es de tipo enumeración de ámbito, no se realizan conversiones; si el otro operando no tiene el mismo tipo, la expresión está mal formada.

- Si uno de los operando es de tipo long double, el otro se convertirá por el doble largo.

- De lo contrario, si uno de los operando es double, el otro se convertirá a double.

- De lo contrario, si uno de los operando es float, el otro se convertirá en float.

- De lo contrario, las promociones integrales se realizarán en ambos operandos. Entonces se aplicarán las siguientes reglas a los operandos promovidos:

- Si ambos operandos tienen el mismo tipo, no se necesita más conversión.

- De lo contrario, si ambos operandos tienen tipos enteros con signo o ambos tienen tipos enteros sin signo, el operando con el tipo de rango de conversión entero menor se convertirá al tipo de la operando con mayor rango.

- De lo contrario, si el operando que tiene tipo entero sin signo tiene rango mayor o igual que el rango del tipo del otro operando, el operando con tipo entero con signo se convertirá a el tipo del operando con tipo entero sin signo.

- De lo contrario, si el tipo del operando con tipo entero con signo puede representar todos los valores del tipo del operando con tipo entero sin signo, el operando con tipo entero sin signo deberá convertir al tipo del operando con tipo entero con signo.

- De lo contrario, ambos operandos se convertirán al tipo entero sin signo correspondiente al tipo del operando con tipo entero con signo.

Ver aquí para una lista eso se actualiza con frecuencia.

 16
Author: legends2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-11 08:25:05

Esta respuesta está dirigida en gran parte a un comentario hecho por @ RafałDowgird:

" El tamaño mínimo de las operaciones es int."- Esto sería muy extraño (¿qué pasa con las arquitecturas que soportan eficientemente char / short las operaciones?) ¿Es esto realmente en la especificación de C++?

Tenga en cuenta que el estándar C++ tiene la muy importante regla "como si". Ver sección 1.8: Ejecución del programa:

3) Esta disposición a veces se llama la regla "como si", porque un la implementación es libre de ignorar cualquier requisito de la Norma siempre y cuando el resultado sea como si el requisito hubiera sido obedecido, como se puede determinar a partir del comportamiento observable del programa.

El compilador no puede establecer un int de 8 bits de tamaño, incluso si fuera el más rápido, ya que el estándar exige un mínimo de 16 bits int.

Por lo tanto, en el caso de un equipo teórico con operaciones súper rápidas de 8 bits, la promoción implícita a int porque la aritmética podría importar. Sin embargo, para muchas operaciones, no puede saber si el compilador realmente hizo las operaciones con la precisión de un int y luego se convirtió a un char para almacenar en su variable, o si las operaciones se realizaron en char todo el tiempo.

Por ejemplo, considere unsigned char = unsigned char + unsigned char + unsigned char, donde la suma se desbordaría (supongamos un valor de 200 para cada uno). Si ascendieras a int, obtendrías 600, que luego se lanzaría implícitamente hacia abajo en un unsigned char, que envolvería el módulo 256, dando así un resultado final de 88. Si no hicieras tales promociones, tendrías que envolver entre las dos primeras adiciones, lo que reduciría el problema de 200 + 200 + 200 a 144 + 200, que es 344, que se reduce a 88. En otras palabras, el programa no conoce la diferencia, por lo que el compilador es libre de ignorar el mandato para realizar operaciones intermedias en int si los operandos tienen un rango inferior a int.

Esto es cierto en general de la suma, la resta y la multiplicación. No es verdad en general para división o módulo.

 5
Author: David Stone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-20 01:24:30

Si excluye los tipos sin signo, hay un orden jerarquía: signed char, short, int, long, long long, float, doble, doble largo. En primer lugar, cualquier cosa que viene antes de int en el arriba se convertirá a int. Entonces, en una operación binaria, el tipo de menor rango se convertirá en el más alto, y el los resultados serán el tipo de la más alta. (Notarás que, desde la jerarquía, en cualquier momento un punto flotante y un tipo integral son involucrado, el tipo integral se convertirá en el flotante tipo de punto.)

Unsigned complica las cosas un poco: perturba el ranking, y partes de la clasificación se convierten en implementación definida. Debido esto, es mejor no mezclar firmado y sin firmar en el mismo expresion. (La mayoría de los expertos en C++ parecen evitar sin firmar a menos que las operaciones bitwise están involucradas. Eso es, al menos, lo que Stroustrup recomienda.)

 3
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 08:08:58

Mi solución al problema obtuvo WA(respuesta incorrecta), luego cambié uno de int a long long inty dio AC(aceptar) . Anteriormente, estaba tratando de hacer long long int += int * int, y después lo rectifico a long long int += long long int * int. Buscando en Google se me ocurrió,

1. Conversiones aritméticas

Condiciones para la conversión de tipos:

Condiciones cumplidas - - - > Conversión

  • Cualquiera de los operando es de tipo long double. --- >Otro operando es convertido al tipo long double.

  • Condición anterior no cumplida y cualquiera de los operando es de tipo double . --- >Otro operando se convierte a type double .

  • Condiciones anteriores no cumplidas y cualquiera de los operando es de tipo float. --- >Otro operando se convierte a type float.

  • Condiciones anteriores no cumplidas (ninguno de los operandos son de tipo flotante). --- >Promociones integrales son se realiza en los operandos de la siguiente manera:

    • Si uno de los operando es de tipo unsigned long, el otro operando se convierte a type unsigned long.
    • Si la condición anterior no se cumple, y si cualquiera de los operando es de tipo long y el otro de tipo unsigned int, ambos operandos se convierten a tipo unsigned long.
    • Si no se cumplen las dos condiciones anteriores, y si cualquiera de los operando es de tipo long , otro operando se convierte a type long.
    • Si no se cumplen las tres condiciones anteriores, y si cualquiera de los operando es de tipo unsigned int, el otro operando se convierte a type unsigned int.
    • Si no se cumple ninguna de las condiciones anteriores, ambos operandos se convierten a type int.

2 . Reglas de conversión de enteros

  • Promociones de enteros:

Tipos Enteros menor que int se promueven cuando se realiza una operación en ellos. Si todos los valores del tipo original se pueden representar como un int, el valor del tipo más pequeño se convierte en un int; de lo contrario, se convierte en un int sin signo. Las promociones de enteros se aplican como parte de las conversiones aritméticas habituales a ciertas expresiones de argumento; operandos de los operadores unarios+, - y~; y operandos de los operadores shift.

  • Conversión de enteros Rango:

    • No hay dos tipos enteros con signo que tengan el mismo rango, incluso si tienen la misma representación.
    • El rango de un tipo entero con signo será mayor que el rango de cualquier tipo entero con signo con menos precisión.
    • El rango de long long int será mayor que el rango de long int, que será mayor que el rango de int, que será mayor que el rango de short int, que será mayor que el rango de signed char.
    • El rango de cualquier no firmado el tipo entero será igual al rango del tipo entero con signo correspondiente, si lo hubiera.
    • El rango de cualquier tipo entero estándar será mayor que el rango de cualquier tipo entero extendido con el mismo ancho.
    • El rango de char será igual al rango de signed char y unsigned char.
    • El rango de cualquier tipo entero con signo extendido en relación con otro tipo entero con signo extendido con la misma precisión está definido por la implementación, pero sigue sujeto a las otras reglas para determinar el rango de conversión entero.
    • 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.
  • Conversiones Aritméticas usuales:

    • Si ambos operandos tienen el mismo tipo, no se necesita más conversión.
    • Si ambos operandos son del mismo tipo entero (con o sin signo), el operando con el tipo de rango de conversión de entero menor se convierte al tipo de el operando con mayor rango.
    • Si el operando que tiene un tipo entero sin signo tiene un rango mayor o igual al rango del tipo del otro operando, el operando con tipo entero con signo se convierte al tipo del operando con tipo entero sin signo.
    • Si el tipo del operando con tipo entero con signo puede representar todos los valores del tipo del operando con tipo entero sin signo, el operando con tipo entero sin signo se convierte al tipo del operando con tipo entero con signo.
    • De lo contrario, ambos operandos se convierten al tipo entero sin signo correspondiente al tipo del operando con tipo entero con signo. Operaciones específicas pueden añadir o modificar la semántica de las operaciones aritméticas habituales.
 2
Author: garakchy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-15 03:21:09

Todo el capítulo 4 habla sobre las conversiones, pero creo que deberías estar más interesado en estas :

4.5 Promociones integrales [conv.prom]
Un r-value de tipo char, signed char, unsigned char short int o unsigned short int se puede convertir a un rvalue de tipo int si int puede representar todos los valores del tipo fuente; other -
wise, el rvalue de origen se puede convertir a un rvalue de tipo unsigned int.
Un rvalue de tipo wchar_t (3.9.1) o un tipo de enumeración (7.2) puede convertirse a un rvalue de la primera
de los siguientes tipos que pueden representar todos los valores de su tipo subyacente: int, unsigned int,
largo, o largo sin signo.
Un rvalue para un bit-field integral (9.6) se puede convertir en un rvalue de tipo int si int puede representar all
los valores del campo bit; de lo contrario, se puede convertir a unsigned int si unsigned int can rep -
vuelva a enviar todos los valores del campo de bits. Si el campo de bits es aún más grande, no hay integral la promoción se aplica a ella. Si el
bit-field tiene un tipo enumerado, se trata como cualquier otro valor de ese tipo para fines de promoción.
Un rvalue de tipo bool se puede convertir en un rvalue de tipo int, con false convirtiéndose en cero y true
convertirse en uno.
Estas conversiones se llaman promociones integrales.

4.6 Promoción en coma flotante [conv.fpprom]
Un rvalue de tipo float se puede convertir en un rvalue de tipo double. El valor no cambia.
Este la conversión se llama promoción de punto flotante.

Por lo tanto, todas las conversiones que involucran float - el resultado es float.

Solo el que involucra a ambos int - el resultado es int : int / int = int

 1
Author: BЈовић,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 07:53:11

El tipo de la expresión, cuando no ambas partes son del mismo tipo, se convertirá al mayor de ambos. El problema aquí es entender cuál es más grande que el otro (no tiene nada que ver con el tamaño en bytes).

En expresiones en las que están involucrados un número real y un número entero, el número entero será promovido a número real. Por ejemplo, en int + float, el tipo de expresión es float.

Las otras diferencias están relacionadas con la capacidad del tipo. Por ejemplo, una expresión que involucre un int y un long int resultará del tipo long int.

 1
Author: Baltasarq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 11:29:07

Advertencia!

Las conversiones ocurren de izquierda a derecha.

Prueba esto:

int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0
 -1
Author: Habib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-14 18:24:17