Los operadores aritméticos aplican operaciones matemáticas estándar a sus operandos.

Operador Nombre del operador Ejemplo Resultado
+ unario más +a El valor de a después de las promociones
- unario menos -a el negativo de a
+ adición a + b la suma de a y B
- sustracción a - b la resta de B de a
* producto a * b el producto de a y B
/ división a / b la división de a por B
% modulo a % b el resto de a dividido por B
~ bit a bit NO ~a el bit a bit NO de a
& bit a bit Y a & b el bit a bit AND de a y B
| O bit a bit a | b el OR bit a bit de a y B
^ XOR bit a bit a ^ b el XOR bit a bit de a y B
<< desplazamiento a la izquierda bit a bit a << b a izquierda desplazada por B
>> desplazamiento a la derecha bit a bit a >> b a desplazado a la derecha por B

Desbordes

La aritmética de enteros sin signo siempre se realiza módulo 2norte
donde n es el número de bits de ese entero en particular. Por ejemplo, para unsigned int, agregando uno a UINT_MAX da ​0​, y restando uno de ​0​ da UINT_MAX.

Cuando la operación aritmética de enteros con signo se desborda (el resultado no encaja en el tipo de resultado), el comportamiento es indefinido: puede ajustarse según las reglas de la representación (típicamente el complemento de 2), puede atrapar en algunas plataformas o debido al compilador opciones (p. ej. -ftrapv en GCC y Clang), o puede ser completamente optimizado por el compilador.

Entorno de punto flotante

Si #pragma STDC FENV_ACCESS se establece en ON, todos los operadores aritméticos de punto flotante obedecen la dirección de redondeo de punto flotante actual e informan errores aritméticos de punto flotante como se especifica en math_errhandling a menos que forme parte de un inicializador estático (en cuyo caso no se generan excepciones de punto flotante y el modo de redondeo es el más cercano).

Contracción de punto flotante

A no ser que #pragma STDC FP_CONTRACT se establece en OFF, toda la aritmética de punto flotante se puede realizar como si los resultados intermedios tuvieran un rango y precisión infinitos, es decir, optimizaciones que omiten los errores de redondeo y las excepciones de punto flotante que se observarían si la expresión se evaluara exactamente como está escrita. Por ejemplo, permite la implementación de (x*y) + z con una sola instrucción de CPU fusionada de adición múltiple u optimización de a = x*x*x*x; como tmp = x*x; a = tmp*tmp.

Sin relación con la contratación, los resultados intermedios de la aritmética de punto flotante pueden tener un rango y una precisión diferentes a los indicados por su tipo, ver FLT_EVAL_METHOD.

Aritmética unaria

Las expresiones del operador aritmético unario tienen la forma.

+expresión (1)
-expresión (2)

1) unario plus (promoción)2) unario menos (negación)

dónde.

expresión - expresión de cualquier tipo aritmético

Tanto el positivo unario como el negativo unario primero aplican promociones integrales a su operando y luego.

  • unary plus devuelve el valor después de la promoción
  • unario menos devuelve el negativo del valor después de la promoción (excepto que el negativo de un NaN es otro NaN)

El tipo de expresión es el tipo después de la promoción y la categoría de valor no es lvalue.

Notas

El menos unario invoca un comportamiento indefinido debido al desbordamiento de enteros con signo cuando se aplica a INT_MIN, LONG_MIN, o LLONG_MIN, en plataformas típicas (complemento de 2).

En C ++, el operador unario + también se puede usar con otros tipos integrados, como matrices y funciones, no así en C.

#include#includeintmain(void)char c ='a';printf("sizeof char: %zu sizeof int: %zun",sizeof c,sizeof+c);printf("-1, where 1 is signed: %dn",-1);printf("-1, where 1 is unsigned: %un",-1u);double complex z =1+2*I;printf("-(1+2i) = %.1f%+.1fn",creal(-z),cimag(-z));

Posible salida:

sizeofchar:1sizeofint:4-1, where 1 is signed:-1-1, where 1 is unsigned:4294967295-(1+2i)=-1.0-2.0

Operadores aditivos

Las expresiones del operador aritmético aditivo binario tienen la forma.

lhs+rhs (1)
lhs-rhs (2)

1) adición: lhs y rhs debe ser uno de los siguientes

  • Ambos tienen tipos aritméticos, incluidos los complejos e imaginarios.
  • uno es un puntero para completar el tipo de objeto, el otro tiene un tipo entero

2) sustracción: lhs y rhs debe ser uno de los siguientes

  • Ambos tienen tipos aritméticos, incluidos los complejos e imaginarios.
  • lhs tiene puntero para completar el tipo de objeto, rhs tiene tipo entero
  • ambos son indicadores para completar objetos de tipos compatibles, ignorando los calificadores

Suma y resta aritmética

Si ambos operandos tienen tipos aritméticos, entonces.

  • Primero, se realizan las conversiones aritméticas habituales.
  • luego, los valores de los operandos después de las conversiones se suman o restan siguiendo las reglas habituales de las matemáticas (para restar, rhs se resta de lhs), excepto eso
    • si un operando es NaN, el resultado es NaN
    • infinito menos infinito es NaN y FE_INVALID es elevado
    • infinito más el infinito negativo es NaN y FE_INVALID es elevado

Las sumas y restas complejas e imaginarias se definen de la siguiente manera (tenga en cuenta que el tipo de resultado es imaginario si ambos operandos son imaginarios y complejos si un operando es real y el otro imaginario, como se especifica en las conversiones aritméticas habituales):

+ o - tu iv u + iv
X x ± u x ± iv (x ± u) ± iv
iy ± u + iy yo (y ± v) ± u + i (y ± v)
x + iy (x ± u) + iy x + yo (y ± v) (x ± u) + i (y ± v)
// work in progress// note: take part of the c/language/conversion example

Aritmética de punteros

  • Si el puntero P apunta a un elemento de una matriz con índice I, luego
    • P+N y N+P son punteros que apuntan a un elemento de la misma matriz con índice I+N
    • P-N es un puntero que apunta a un elemento de la misma matriz con índice tt }

El comportamiento se define solo si tanto el puntero original como el puntero de resultado apuntan a elementos de la misma matriz o uno más allá del final de esa matriz. Tenga en cuenta que ejecutar p-1 cuando p apunta al primer elemento de una matriz es un comportamiento indefinido y puede fallar en algunas plataformas.

  • Si el puntero P1 apunta a un elemento de una matriz con índice I (o uno más allá del final) y P2 apunta a un elemento de la misma matriz con índice J (o uno más allá del final), entonces
    • P1-P2 tiene el valor igual a J-I y el tipo ptrdiff_t (que es un tipo entero con signo, generalmente la mitad del tamaño del objeto más grande que se puede declarar)

El comportamiento se define solo si el resultado encaja ptrdiff_t.

A los efectos de la aritmética de punteros, un puntero a un objeto que no es un elemento de ninguna matriz se trata como un puntero al primer elemento de una matriz de tamaño 1.

// work in progressint n =4, m =3;int a[n][m];// VLA of 4 VLAs of 3 ints eachint(*p)[m]= a;// p == &a[0] 
p = p +1;// p == &a[1] (pointer arithmetic works with VLAs just the same)(*p)[2]=99;// changes a[1][2]

Operadores multiplicativos

Las expresiones del operador aritmético multiplicativo binario tienen la forma.

lhs*rhs (1)
lhs/rhs (2)
lhs%rhs (3)

1) multiplicación. lhs y rhs debe tener tipos aritméticos2) división. lhs y rhs debe tener tipos aritméticos3) recordatorio. lhs y rhs debe tener tipos enteros

  • primero, se realizan las conversiones aritméticas habituales. Luego...

Multiplicación

El operador binario * realiza la multiplicación de sus operandos (después de las conversiones aritméticas habituales) siguiendo las definiciones aritméticas habituales, excepto que.

  • si un operando es un NaN, el resultado es un NaN
  • la multiplicación si infinito por cero da NaN y FE_INVALID es elevado
  • la multiplicación de infinito por un valor distinto de cero da infinito (incluso para argumentos complejos)

Debido a que en C, cualquier valor complejo con al menos una parte infinita como infinito, incluso si su otra parte es un NaN, las reglas aritméticas habituales no se aplican a la multiplicación complejo-complejo. Otras combinaciones de operandos flotantes siguen la siguiente tabla:

* tu iv u + iv
X xu yo (xv) (xu) + i (xv)
iy yo (yu) −yv (−yv) + i (yu)
x + iy (xu) + yo (yu) (−yv) + i (xv) reglas especiales

Además del manejo infinito, no se permite que la multiplicación compleja sobrepase los resultados intermedios, excepto cuando #pragma STDC CX_LIMITED_RANGE se establece en ON, en cuyo caso el valor puede calcularse como si fuera (x + iy) × (u + iv) = (xu-yv) + i (yu + xv), ya que el programador asume la responsabilidad de limitar el rango de los operandos y lidiar con los infinitos.

A pesar de no permitir el desbordamiento indebido, la multiplicación compleja puede generar excepciones falsas de punto flotante (de lo contrario, es prohibitivamente difícil implementar versiones sin desbordamiento).

#include#include#include#includeintmain(void)// TODO simpler cases, take some from C++double complex z =(1+0*I)*(INFINITY + I*INFINITY);// textbook formula would give// (1+i0)(∞+i∞) ⇒ (1×∞ – 0×∞) + i(0×∞+1×∞) ⇒ NaN + I*NaN// but C gives a complex infinityprintf("%f + i*%fn",creal(z),cimag(z));// textbook formula would give// cexp(∞+iNaN) ⇒ exp(∞)×(cis(NaN)) ⇒ NaN + I*NaN// but C gives  ±∞+i*nandouble complex y =cexp(INFINITY + I*NAN);printf("%f + i*%fn",creal(y),cimag(y));

Posible salida:

inf + i*inf 
inf + i*nan

División

El operador binario / divide el primer operando por el segundo (después de las conversiones aritméticas habituales) siguiendo las definiciones aritméticas habituales, excepto que.

  • cuando el tipo después de las conversiones aritméticas habituales es un tipo entero, el resultado es el cociente algebraico (no una fracción), redondeado en la dirección definida por la implementación(hasta C99)truncado hacia cero(ya que C99)
  • si un operando es un NaN, el resultado es un NaN
  • si el primer operando es un infinito complejo y el segundo operando es finito, entonces el

El resultado del operador / es un infinito complejo.

  • si el primer operando es finito y el segundo operando es un infinito complejo, entonces el

el resultado del operador / es cero.

Debido a que en C, cualquier valor complejo con al menos una parte infinita como infinito, incluso si su otra parte es un NaN, las reglas aritméticas habituales no se aplican a la división complejo-complejo. Otras combinaciones de operandos flotantes siguen la siguiente tabla:

/ tu iv
X x / u yo (−x / v)
iy yo (y / u) y / v
x + iy (x / u) + i (y / u) (y / v) + i (−x / v)

Además del manejo infinito, no se permite que la división compleja sobrepase los resultados intermedios, excepto cuando #pragma STDC CX_LIMITED_RANGE se establece en ON, en cuyo caso el valor puede calcularse como si (x + iy) / (u + iv) = [(xu+yv)+i(yu-xv)]/ (u2
+ v2
), ya que el programador asume la responsabilidad de limitar el rango de los operandos y tratar con los infinitos.

A pesar de no permitir el desbordamiento indebido, la división compleja puede generar falsas excepciones de punto flotante (de lo contrario, es prohibitivamente difícil implementar versiones sin desbordamiento).

Si el segundo operando es cero, el comportamiento no está definido, excepto que si se admite la aritmética de punto flotante IEEE y se está llevando a cabo la división de punto flotante, entonces.

  • Dividir un número distinto de cero por ± 0.0 da el infinito correctamente firmado y FE_DIVBYZERO es elevado
  • Dividir 0.0 por 0.0 da NaN y FE_INVALID es elevado

Recordatorio

El operador binario% produce el resto de la división del primer operando por el segundo (después de las conversiones aritméticas habituales).

El signo del resto se define de tal manera que si el cociente a/b es representable en el tipo de resultado, entonces (a/b)*b + a%b == a.

Si el segundo operando es cero, el comportamiento no está definido.

Si el cociente a/b no es representable en el tipo de resultado, el comportamiento de ambos a/b y a%b no está definido (eso significa INT_MIN%-1 no está definido en los sistemas de complemento a 2).

Nota: el operador restante no funciona en tipos de punto flotante, la función de biblioteca fmod proporciona esa funcionalidad.

Lógica bit a bit

Las expresiones del operador aritmético bit a bit tienen la forma.

~rhs (1)
lhs&rhs (2)
lhs|rhs (3)
lhs^rhs (4)

1) bit a bit NO2) bit a bit Y3) O bit a bit4) XOR bit a bit

dónde.

lhs, rhs - expresiones de tipo entero

Primero, operadores &, ^ y | realiza conversiones aritméticas habituales en ambos operandos y el operador ~ realiza promociones de enteros en su único operando.

Luego, los correspondientes operadores lógicos binarios se aplican bit a bit; es decir, cada bit del resultado se establece o borra de acuerdo con la operación lógica (NOT, AND, OR o XOR), aplicada a los bits correspondientes de los operandos.

Nota: los operadores bit a bit se utilizan comúnmente para manipular conjuntos de bits y máscaras de bits.

Nota: para los tipos sin firmar (después de la promoción), la expresión ~ E es equivalente al valor máximo representable por el tipo de resultado menos el valor original de E.

#include#includeintmain(void)mask),(a&~mask),(a&mask));

Posible salida:

Value:0x12345678 mask:0xf0
Setting bits:0x123456f8
Clearing bits:0x12345608
Selecting bits:0x70

Operadores de turno

Las expresiones del operador de desplazamiento bit a bit tienen la forma.

lhs<<rhs (1)
lhs>>rhs (2)

1) desplazamiento a la izquierda de lhs por rhs bits2) desplazamiento a la derecha de lhs por rhs bits

dónde.

lhs, rhs - expresiones de tipo entero

Primero, las promociones de enteros se realizan, individualmente, en cada operando (Nota: esto es diferente a otros operadores aritméticos binarios, que realizan todas las conversiones aritméticas habituales). El tipo de resultado es el tipo de lhs después de la promoción.

Por no firmado lhs, El valor de LHS << RHS es el valor de LHS * 2RHS
, valor máximo de módulo reducido del tipo de retorno más 1 (es decir, se realiza un desplazamiento a la izquierda a nivel de bits y se descartan los bits que se desplazan fuera del tipo de destino). Para firmado lhs con valores no negativos, el valor de LHS << RHS es LHS * 2RHS
si es representable en el tipo promocionado de lhs, de lo contrario, el comportamiento no está definido.

Por no firmado lhs y por firmado lhs con valores no negativos, el valor de LHS >> RHS es la parte entera de LHS / 2RHS
. Por negativo LHS, El valor de LHS >> RHS está definido por la implementación donde en la mayoría de las implementaciones, esto realiza un desplazamiento aritmético a la derecha (de modo que el resultado sigue siendo negativo). Así, en la mayoría de las implementaciones, desplazar a la derecha un signo LHS llena los nuevos bits de orden superior con el bit de signo original (es decir, con 0 si no era negativo y 1 si era negativo).

En cualquier caso, el comportamiento es indefinido si rhs es negativo o es mayor o igual al número de bits en el promovido lhs.

#includeenumONE=1, TWO=2;intmain(void)char c =0x10;unsignedlonglong ulong_num =0x123;printf("0x123 << 1  = %#llxn""0x123 << 63 = %#llxn"// overflow truncates high bits for unsigned numbers"0x10  << 10 = %#xn",// char is promoted to int
           ulong_num <<1, ulong_num <<63, c <<10);longlong long_num =-1000;printf("-1000 >> 1 = %lldn", long_num >> ONE);// implementation defined

Posible salida:

0x123<<1=0x2460x123<<63=0x80000000000000000x10<<10=0x4000-1000>>1=-500

Referencias

  • Estándar C11 (ISO / IEC 9899: 2011):
    • 6.5.3.3 Operadores aritméticos unarios (p: 89)
    • 6.5.5 Operadores multiplicativos (p: 92)
    • 6.5.6 Operadores aditivos (p: 92-94)
    • 6.5.7 Operadores de desplazamiento bit a bit (p: 94-95)
    • 6.5.10 Operador AND bit a bit (p: 97)
    • 6.5.11 Operador OR exclusivo bit a bit (p: 98)
    • 6.5.12 Operador OR inclusivo bit a bit (p: 98)
  • Estándar C99 (ISO / IEC 9899: 1999):
    • 6.5.3.3 Operadores aritméticos unarios (p: 79)
    • 6.5.5 Operadores multiplicativos (p: 82)
    • 6.5.6 Operadores aditivos (p: 82-84)
    • 6.5.7 Operadores de desplazamiento bit a bit (p: 84-85)
    • 6.5.10 Operador AND bit a bit (p: 87)
    • 6.5.11 Operador OR exclusivo bit a bit (p: 88)
    • 6.5.12 Operador OR inclusivo bit a bit (p: 88)
  • Estándar C89 / C90 (ISO / IEC 9899: 1990):
    • 3.3.3.3 Operadores aritméticos unarios
    • 3.3.5 Operadores multiplicativos
    • 3.3.6 Operadores aditivos
    • 3.3.7 Operadores de desplazamiento bit a bit
    • 3.3.10 Operador AND bit a bit
    • 3.3.11 Operador OR exclusivo bit a bit
    • 3.3.12 Operador OR inclusivo bit a bit

Ver también

Precedencia del operador.

Operadores comunes
asignación incremento
decremento
aritmética lógico comparación miembro
acceso
otro

a = b a += b a -= b a *= b a /= b a %= b a &= b a |= b a ^= b a <<= b a >>= b.

++a --a a++ a--

+a -a a + b a - b a * b a / b a % b ~a a & b a | b a ^ b a << b a >> b.

!a a && b a || b.

a == b a != b a < b a > b a <= b a >= b.

a[b] *a &a a->b a.b.

a(...) a, b (type) a ? : sizeof _Alignof(desde C11).