Operadores aritméticos
Devuelve el resultado de una operación aritmética específica.
Nombre operador | Sintaxis | Sobrecargable | ejemplos de prototipos (para class T) | |
---|---|---|---|---|
Definición dentro de clase | Definición fuera de clase | |||
más unario | +a
|
Sí | T T::operator+() const; | T operator+(const T &a); |
menos unario | -a
|
Sí | T T::operator-() const; | T operator-(const T &a); |
suma | a + b
|
Sí | T T::operator+(const T2 &b) const; | T operator+(const T &a, const T2 &b); |
resta | a - b
|
Sí | T T::operator-(const T2 &b) const; | T operator-(const T &a, const T2 &b); |
multiplicación | a * b
|
Sí | T T::operator*(const T2 &b) const; | T operator*(const T &a, const T2 &b); |
división | a / b
|
Sí | T T::operator/(const T2 &b) const; | T operator/(const T &a, const T2 &b); |
módulo | a % b
|
Sí | T T::operator%(const T2 &b) const; | T operator%(const T &a, const T2 &b); |
NOT aplicado a bits | ~a
|
Sí | T T::operator~() const; | T operator~(const T &a); |
AND aplicado a bits | a & b
|
Sí | T T::operator&(const T2 &b) const; | T operator&(const T &a, const T2 &b); |
OR aplicado a bits | a | b
|
Sí | T T::operator|(const T2 &b) const; | T operator|(const T &a, const T2 &b); |
XOR aplicado a bits | a ^ b
|
Sí | T T::operator^(const T2 &b) const; | T operator^(const T &a, const T2 &b); |
desplazamiento izquierda de bits | a << b
|
Sí | T T::operator<<(const T2 &b) const; | T operator<<(const T &a, const T2 &b); |
desplazamiento derecha de bits | a >> b
|
Sí | T T::operator>>(const T2 &b) const; | T operator>>(const T &a, const T2 &b); |
|
Contenido |
[editar] Explicación
Todos los operadores aritméticos calculan el resultado de la operación aritmética específica y devuelven el resultado. Los argumentos no se modifican.
[editar] Conversiones
Si el operando que se pasa al operador aritmético es entero o tipo enumeración sin ámbito, entonces antes de cualquier otra acción (pero después de la conversión de lvalue a rvalue, si corresponde), el operando sufre una promoción entera. Si un operando tiene tipo matriz o función, se aplican las conversiones matriz a puntero y función a puntero.
Para los operadores binarios (excepto desplazamientos), si los operandos promocionados tienen tipos diferentes, se aplica un conjunto adicional de conversiones implícitas, conocido como conversiones aritméticas comunes con el objetivo de producir el tipo común (también accesible a través del tipo std::common_type). Si, antes de cualquier promoción enters, un operando es de tipo enumerado y el otro de tipo coma flotante o de tipo diferente de enumerado, este comportamiento está en desuso. (desde C++20)
- Si cualquiera de los operandos tiene un tipo enumerado con ámbito, no se realiza ninguna conversión: el otro operando y el tipo de retorno deben tener el mismo tipo.
- En otro caso, si cualquier operando es long double, el otro operando se convierte a long double
- En otro caso, si cualquier operando es double, el otro operando se convierte a double
- En otro caso, si cualquier operando es float, el otro operando se convierte a float
- En otro caso, el operando tiene tipo entero (porque bool, char, char16_t, char32_t, wchar_t, y enumeración sin ámbito están promocionados en este punto) y se aplica conversiones enteras para producir el tipo común, como los siguientes:
- Si ambos operandos tienen signo o no tienen signo, el operador con menor rango de conversión se convierte al operando con el mayor rango de conversión de entero.
- En otro caso, si el rango de conversión del operando sin signo es mayor o igual qur el rango de conversión del operando con signo, el operando con signo se convierte al tipo del operando sin signo.
- En otro caso, si el tipo del operando con signo puede representar todos los valores del operando sin signo, el operando sin signo se convierte al tipo del operando con signo.
- En otro caso, ambos operandos se convierten al equivalente sin signo del tipo del operador con signo.
El rango de conversión anterior aumenta en orden bool, signed char, short, int, long, long long. El rango de cualquier tipo sin signo es igual al rango del tipo con signo correspondiente. El rango de char es igual al rango de signed char y unsigned char. El rango de char16_t, char32_t, y wchar_t son iguales a los rangos de sus tipos subyacentes.
[editar] Desbordamientos
La aritmética de enteros sin signo siempre se realiza sobre modulo 2n
, donde n es el número de bits de ese entero en particular. Por ejemplo, para unsigned int, sumando uno a UINT_MAX obtenemos 0, y restando uno a 0 obtenemos UINT_MAX.
Cuando una operación aritmética entera con signo sufre un desbordamiento (el resultado no cabe el el tipo del resultado), el comportamiento es indeterminado: puede reiniciar acorde con las reglas de representación (típicamente complemento a 2), puede parar la ejecución en algunas plataformas o por las opciones del compilador (por ejemplo, -ftrapv
en GCC y Clang), o se puede completar optimized out by the compiler.
[editar] Entorno de coma flotante
Si se soporta
#pragma STDC FENV_ACCESS y está establecido como ON
, todos los operadores aritméticos de coma flotante obedecen la dirección de redondeo actual e informan de los errores aritméticos de coma flotante como se especifica en math_errhandling a menos que sea parte de un inicializador estático (en cuyo caso no se generan las excepciones de coma flotante y modo de redondeo es al más cercano).
[editar] Contracción de coma flotante
A menos que se soporte
#pragma STDC FP_CONTRACT y este establecido a OFF
, toda la aritmética de coma flotante se puede realizar como si los resultados intermedios tuvieran rango y precisión infinitos, es decir, se permiten optimizaciones que omiten errores de redondeo y excepciones de coma flotante. Por ejemplo, C++ permite la implementación de (x*y) + z con una sola instrucción de CPU de adicción múltiple fusionada o la optimización de a = x*x*x*x; como tmp = x*x; a = tmp*tmp.
Sin relación con la contracción, los resultados intermedios de la aritmética de coma flotante pueden tener un rango y una precisión diferentes a los indicados por su tipo, ser FLT_EVAL_METHOD.
Formalmente, el estándar de C++ no garantiza la precisión de las operaciones de coma flotante.
[editar] Operadores aritméticos unarios
Las expresiones del operador aritmético unario tienen la forma
+ expression
|
(1) | ||||||||
- expression
|
(2) | ||||||||
El operador más unario integrado retorna el valor de su operando. La única situación donde no es una instrucción vacía es cuando el operando tiene tipo entero o tipo enumerado son ámbito, que se cambia por la promoción entera, por ejemplo, se convierte char a int o si el operando está sujeto a una conversión lvalue a rvalue, matriz a puntero, o función a puntero.
El operador menos unario integrado calcula el negativo de su operando promocionado. Para a
sin singo, el valor de -a
es 2b
-a, done b
es el número de bits después de la promoción.
En la resolución de sobrecarga de operadores definidos por usuario, para cada tipo aritmético promocionado A
y para cada tipo T
, los siguientes modelos de función participan en la resolución de sobrecarga:
A operator+(A) |
||
T* operator+(T*) |
||
A operator-(A) |
||
#include <iostream> int main() { char c = 0x6a; int n1 = 1; unsigned char n2 = 1; unsigned int n3 = 1; std::cout << "char: " << c << " int: " << +c << '\n' << "-1, donde 1 es signed: " << -n1 << '\n' << "-1, donde 1 es unsigned char: " << -n2 << '\n' << "-1, donde 1 es unsigned int: " << -n3 << '\n'; char a[3]; std::cout << "tamaño de matriz: " << sizeof a << '\n' << "tamaño de puntero: " << sizeof +a << '\n'; }
Salida:
char: j int: 106 -1, donde 1 es signed: -1 -1, donde 1 es unsigned char: -1 -1, donde 1 es unsigned int: 4294967295 tamaño de matriz: 3 tamaño de puntero: 8
[editar] Operadores de adición
La expresión del operador aritmético de adición binaria tiene la forma
lhs + rhs
|
(1) | ||||||||
lhs - rhs
|
(2) | ||||||||
- ambos tienen tipo aritmético o enumerado sin ámbito. En este caso, se realizan las conversiones aritméticas usuales en ambos operandos y se determina el tipo del resultado.
- uno es un puntero a tipo objeto completo, el otro tiene tipo entero o enumerado sin ámbito. En este caso, el tipo del resultado tiene el tipo del puntero.
- ambos tienen tipo aritmético o enumerado sin ámbito. En este caso, se realiza las conversiones aritméticas usuales en ambos operandos y se determina el tipo del resultado.
- lhs es un puntero a tipo de objeto completo, rhs tiene tipo entero o enumerado sin ámbito. En este caso, el tipo del resultado es el tipo del puntero.
- ambos son punteros al mismo tipos de onjeto completo, ignorando calificadores const y volatile. En este caso, el tipo del resultado es std::ptrdiff_t.
Con operandos de tipo aritmético o enumeración, el resultado de la suma binaria es la suma de los operandos (después de las conversiones aritméticas usuales), y el resultado del operador menos binario es el resultado de la sustracción del segundo operando al primero (después de las conversiones aritméticas usuales), excepto que, si el tipo soporta aritmética de como flotante IEEE (ver std::numeric_limits::is_iec559),
- si uno de los operandos es NaN, el resultado es NaN
- infinito menos infinito es NaN y se establece FE_INVALID
- infinito más infinito negativo es NaN y se establece FE_INVALID
Si alguno de los operandos es un puntero, se aplican las siguiente reglas:
- Un puntero a un objeto no matriz se trata como un puntero al primer elemento de una matriz de tamaño 1.
- Si el puntero
P
apunta ali-esimo
elemento de una matriz, entonces las expresionesP+n
,n+P
, yP-n
son punteros del mismo tipo que apuntan respectivamente a los elementosi+n
,i+n
, yi-n
de la misma matriz. El resultado de la suma de puntero también puede ser un puntero que pasa del final (es decir, el punteroP
con la expresiónP-1
apunta el último elemento de la matriz. En cualquier otra situación (es decir, intenta generar un puntero que no apunta a un elemento de la misma matriz o uno más allá del final) crea un comportamiento indeterminado. - Si el puntero
P
apunta el elementoi-esimo
de una matriz, y el punteroQ
apunta al elementoj-esimo
de la misma matriz, la expresiónP-Q
tiene el valor i-j, si el valor se ajusta a std::ptrdiff_t. Ambos operandos deben apuntar a elementos la misma matriz (o uno pasado el final), en otro caso el comportamiento es indeterminado. Si el resultado no se ajusta a std::ptrdiff_t, el comportamiento es indeterminado. - En cualquier caso, si el tipo del puntero es diferente el tipo del elemento de la matriz, sin tener en cuenta la calificaciones const-volatile, en todos los niveles si los elementos son punteros en sí mismo, el comportamiento de la aritmética de punteros es indeterminado. En particular, la aritmética de punteros con puntero a base, que apunta a un elemento de una matriz de objetos derivados no está definida.
- Si el valor 0 se suma o resta al puntero, el resultado es el puntero, sin cambios. Si dos punteros que apuntan a mismo objeto o se pasan uno del final de la misma matriz, o son punteros nulos, entonces el resultado de la resta es igual a (std::ptrdiff_t)0.
Estos operadores aritméticos de punteros permiten que los punteros cumplan los requisitos RandomAccessIterator.
En la resolución de sobrecarga de operadores definidos por usuario, para cada par de tipos aritméticos promocionados L
y R
y para tipo de objeto T
, los siguiente modelos de funciones participan en la resolución de sobrecarga:
LR operator+(L, R) |
||
LR operator-(L, R) |
||
T* operator+(T*, std::ptrdiff_t) |
||
T* operator+(std::ptrdiff_t, T*) |
||
T* operator-(T*, std::ptrdiff_t) |
||
std::ptrdiff_t operator-(T*, T*) |
||
donde LR
es el resultado de las conversiones usuales en L
y R
#include <iostream> int main() { char c = 2; unsigned int un = 2; int n = -10; std::cout << " 2 + (-10), donde 2 es char = " << c + n << '\n' << " 2 + (-10), donde 2 es sin singo = " << un + n << '\n' << " -10 - 2.12 = " << n - 2.12 << '\n'; char a[4] = {'a', 'b', 'c', 'd'}; char* p = &a[1]; std::cout << "Ejemplos de suma de punteros: " << *p << *(p + 2) << *(2 + p) << *(p - 1) << '\n'; char* p2 = &a[4]; std::cout << "Resta de punteros: " << p2 - p << '\n'; }
Salida:
2 + (-10), donde 2 es char = -8 2 + (-10), donde 2 es sin singo = 4294967288 -10 - 2.12 = -12.12 Ejemplos de suma de punteros: bdda Resta de punteros: 3
[editar] Los operadores multiplicativos
Las expresiones del operador aritmético multiplicativo binario tienen la forma
lhs * rhs
|
(1) | ||||||||
lhs / rhs
|
(2) | ||||||||
lhs % rhs
|
(3) | ||||||||
Para los tres operadores, se realizan las conversiones aritméticas usuales en ambos operandos y se determina el tipo del resultado.
El operador binario * realiza la multiplicación de sus operandos (después de la conversiones aritméticas usuales), excepto que, para la multiplicación de coma flotante,
- multiplicación de NaN con cualquier otro número da NaN
- multiplicación de infinito por cero da NaN y se lanza FE_INVALID
El operador binario / divide el primer operando por el segundo (después de las conversiones aritméticas usuales).
Para los operandos enteros, se obtiene el cociente algebraico.
Se redondea el cociente en la dirección definida por la implementación. |
(hasta C++11) |
El cociente se trunca hacia cero (se descarta la parte fraccional). |
(desde C++11) |
Si el segundo operando es cero, el comportamiento es indeterminado, excepto que si tiene lugar una división de coma flotante y el tipo soporta la aritmética de coma flotante IEEE (ver std::numeric_limits::is_iec559), entonces:
- si un operando es NaN, el resultado es NaN.
- dividir un número no cero por ±0.0 da infinito con el signo correcto y se lanza FE_DIVBYZERO.
- dividir 0.0 por 0.0 da NaN y se lanza FE_INVALID.
El operador binario % obtiene el resto de la división entera entre el primer operando por el segundo (después de las conversiones aritméticas usuales); tenga en cuenta que los tipos de operando deben ser tipos enteros). Si el cociente a/b
es representable en el tipo del resultado, (a/b)*b + a%b == a. Si el segundo operando es cero, el comportamiento es indeterminado. Si el cociente a/b
no es representable en el tipo del resultado, el comportamiento de a/b
y a%b
es indeterminado (esto significa que INT_MIN%-1 es indeterminado en sistemas de complemento a 2).
Nota: Hasta C++11, si uno o ambos operandos del operador binario % eran negativos, el signo del resto estaba definida por la implementación, ya que depende de la dirección de redondeo de la división entera. En esta caso la función std::div provee un comportamiento bien definido.
Nota: para el resto de coma flotante, ver std::remainder y std::fmod.
En la resolución de sobrecargas de operadores definidas por usuario, para cada par de tipos aritméticos promocionados LA
y RA
y para cada par de tipos enteros promocionados LI
y RI
los siguientes modelos de función participan en la resolución de la sobrecarga:
LRA operator*(LA, RA) |
||
LRA operator/(LA, RA) |
||
LRI operator%(LI, RI) |
||
donde LRx
es el resultado de las conversiones aritméticas usuales de Lx
y Rx
#include <iostream> int main() { char c = 2; unsigned int un = 2; int n = -10; std::cout << "2 * (-10), donde 2 es un char = " << c * n << '\n' << "2 * (-10), donde 2 es sin signo = " << un * n << '\n' << "-10 / 2.12 = " << n / 2.12 << '\n' << "-10 / 21 = " << n / 21 << '\n' << "-10 % 21 = " << n % 21 << '\n'; }
Salida:
2 * (-10), donde 2 es un char = -20 2 * (-10), donde 2 es sin signo = 4294967276 -10 / 2.12 = -4.71698 -10 / 21 = 0 -10 % 21 = -10
[editar] Operadores lógicos sobre bits
Las expresiones de operador aritmético sobre bits tienen la forma
~ rhs
|
(1) | ||||||||
lhs & rhs
|
(2) | ||||||||
lhs | rhs
|
(3) | ||||||||
lhs ^ rhs
|
(4) | ||||||||
El resultado del operador ~ es el NOT (no lógico) sobre los bits (complemento a uno) del valor del argumento (después de la promoción). El resultado del operador & es el AND (y lógico) sobre los bits del valor de los operandos (después de las conversiones aritméticas usuales). El resultado del operador | es el OR (o lógico) sobre los bits del valor de los operandos (después de las conversiones aritméticas usuales). El resultado del operador ^ es el XOR (o exclusivo) sobre los bits del valor de los operandos (después de las conversiones aritméticas usuales).
En la resolución de sobrecarga de operadores definida por usuario, para cada par de tipos enteros promocionados L
y R
los siguientes modelos de funciones participan en la resolución de la sobrecarga:
R operator~(R) |
||
LR operator&(L, R) |
||
LR operator^(L, R) |
||
LR operator|(L, R) |
||
donde LR
es el resultado de las conversiones aritméticas usuales de L
y R
#include <iostream> int main() { std::cout << std::hex << std::showbase; uint16_t mask = 0x00f0; uint32_t a = 0x12345678; std::cout << "Valor: " << a << " máscara: " << mask << '\n' << "Estableciendo bits: " << (a | mask) << '\n' << "Limpiando bits: " << (a & ~mask) << '\n' << "Seleccionando bits: " << (a & mask) << '\n'; }
Salida:
Valor: 0x12345678 máscara: 0xf0 Estableciendo bits: 0x123456f8 Limpiando bits: 0x12345608 Seleccionando bits: 0x70
[editar] Operadores de desplazamiento de bits
Las expresiones del operador de desplazamiento de bits tienen la forma
lhs << rhs
|
(1) | ||||||||
lhs >> rhs
|
(2) | ||||||||
El tipo de retorno es el tipo del operando izquierdo después de la promoción entera.
Para a
sin signo y positiva, el valor de a << b
es el valor de a * 2b
, módulo reducido del valor máximo del tipo de retorno más uno (es decir, se realiza el desplazamiento izquierda de los bits y los bits que quedan fuera del tipo de destino se descartan).
Para a
con signo y positiva,
El valor de |
(hasta C++14) |
el valor de |
(desde C++14) |
Para a
negativa, el comportamiento de a << b
es indeterminado.
Para a
sin signo y a
con signo con valores no negativos, el valor de a >> b
es la parte entera de a/2b
. Para a
negativa, el valor de a >> b
es definida por la implementación (en muchas implementaciones, se realiza un desplazamiento a la derecha aritmético, por lo que el resultado continua siendo negativo).
En cualquier caso, si el valor del operando derecho es negativo o es mayor o igual al número de bits del operando izquierdo promocionado, el comportamiento es indeterminado.
En la resolución de sobrecarga de operadores definidos por usuario, para cada par de tipos enteros promocionados L
y R
, los siguientes modelo de función participan en la resolución de la sobrecarga:
L operator<<(L, R) |
||
L operator>>(L, R) |
||
#include <iostream> enum {ONE=1, TWO=2}; int main() { std::cout << std::hex << std::showbase; char c = 0x10; unsigned long long ull = 0x123; std::cout << "0x123 << 1 = " << (ull << 1) << '\n' << "0x123 << 63 = " << (ull << 63) << '\n' // desbordamiento << "0x10 << 10 = " << (c << 10) << '\n'; // se promociona char a int long long ll = -1000; std::cout << std::dec << "-1000 >> 1 = " << (ll >> ONE) << '\n'; }
Salida:
0x123 << 1 = 0x246 0x123 << 63 = 0x8000000000000000 0x10 << 10 = 0x4000 -1000 >> 1 = -500
[editar] Biblioteca estándar
Los operadores aritméticos se sobrecargan en muchos tipos de la biblioteca estándar.
[editar] Los operadores unarios aritméticos
Implementa + unario y - unario. (función miembro pública de std::chrono::duration )
| |
Aplica operadores unarios a números complejos. (plantilla de función) | |
se aplica un operador aritmético unario a cada elemento del valarray (función miembro pública de std::valarray )
|
[editar] Operadores de adición
Realiza operaciones de suma y resta que involucran un punto de tiempo. (plantilla de función) | |
Implementa operaciones aritméticas con duraciones como argumentos. (plantilla de función) | |
(C++20) |
Suma or resta a un objeto year_month_day algún número de años o meses. (función) |
Concatena dos cadenas, o una cadena y un carácter (plantilla de función) | |
avanza o decrementa el iterador (función miembro pública de std::reverse_iterator )
| |
avanza o decrementa el iterador (función miembro pública de std::move_iterator )
| |
Realiza la aritmética de números complejos en dos valores complejos o un complejo y un escalar. (plantilla de función) | |
se aplica operadores binarios a cada elemento de dos valarrays, o un valarray y un valor (plantilla de función) |
[editar] Los operadores multiplicativos
Implementa operaciones aritméticas con duraciones como argumentos. (plantilla de función) | |
Realiza la aritmética de números complejos en dos valores complejos o un complejo y un escalar. (plantilla de función) | |
se aplica operadores binarios a cada elemento de dos valarrays, o un valarray y un valor (plantilla de función) |
[editar] Los operadores lógicos sobre bits
realiza operación binaria AND, OR, XOR y NOT (función miembro pública de std::bitset )
| |
Realiza operaciones lógicas binarias en conjuntos de bits. (función) | |
se aplica un operador aritmético unario a cada elemento del valarray Original: applies a unary arithmetic operator to each element of the valarray The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. (función miembro pública de std::valarray )
| |
se aplica operadores binarios a cada elemento de dos valarrays, o un valarray y un valor Original: applies binary operators to each element of two valarrays, or a valarray and a value The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. (plantilla de función) |
[editar] Operadores de desplazamiento sobre bits
se aplica operadores binarios a cada elemento de dos valarrays, o un valarray y un valor Original: applies binary operators to each element of two valarrays, or a valarray and a value The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. (plantilla de función) | |
realiza desplazamiento binario a la izquierda y la derecha Original: performs binary shift left and shift right The text has been machine-translated via Google Translate. You can help to correct and verify the translation. Click here for instructions. (función miembro pública de std::bitset )
|
[editar] Operadores de inserción/extracción en Stream
A lo largo de la biblioteca estándar, los operadores de desplazamiento de bits se sobrecargan comúnmente en los stream de E/S (std::ios_base& o una de las clases derivadas) como los tipos del operando izquierdo y de retorno. Tales operadores son conocidos como operadores de inserción en stream y extracción en stream:
extraer datos con formato (función miembro pública de std::basic_istream )
| |
extrae caracteres y matrices de caracteres (plantilla de función) | |
Inserta datos con formato. (función miembro pública de std::basic_ostream<CharT,Traits> )
| |
inserciones de datos caracter (función) | |
Serializa y deserializa un número complejo. (plantilla de función) | |
Realiza entrada y salida de flujos de conjuntos de bits. (función) | |
Realiza secuencia de E/S en cadenas de texto (plantilla de función) | |
realiza flujo de entrada y de salida en el motor de números pseudo-aleatorios (función) | |
realiza flujo de entrada y salida en la distribución de números pseudo-aleatorios (función) |
[editar] Ver también
Operadores comunes | ||||||
---|---|---|---|---|---|---|
Asignación | Incremento/decremento | Aritméticos | Lógicos | Comparación | Acceso a miembro | Otros |
a = b |
++a |
+a |
!a |
a == b |
a[b] |
a(...) |
Operadores especiales | ||||||
static_cast Convierte de un tipo a otro tipo relacionado |
Documentación de C para Operadores aritméticos
|