Esta es una lista de operadores en los lenguajes de programación C y C++ . Todos los operadores (excepto typeof ) enumerados existen en C++; la columna "Incluido en C" indica si un operador también está presente en C. Tenga en cuenta que C no admite la sobrecarga de operadores .
Cuando no está sobrecargado, para los operadores &&
, ||
y ,
(el operador de coma ), hay un punto de secuencia después de la evaluación del primer operando.
C++ también contiene los operadores de conversión de tiposconst_cast
, static_cast
, dynamic_cast
y reinterpret_cast
. El formato de estos operadores implica que su nivel de precedencia no es importante.
La mayoría de los operadores disponibles en C y C++ también están disponibles en otros lenguajes de la familia C, como C# , D , Java , Perl y PHP , con la misma precedencia, asociatividad y semántica.
Para los fines de estas tablas, a
, b
, y c
representan valores válidos (literales, valores de variables o valor de retorno), nombres de objetos o valores l, según corresponda. R
, S
y T
representan cualquier tipo y K
un tipo de clase o tipo enumerado. Algunos de los operadores tienen ortografías alternativas que utilizan dígrafos y trígrafos o sinónimos de operador.
Todos los operadores aritméticos existen en C y C++ y pueden sobrecargarse en C++.
En C++, todos los operadores de comparación se pueden sobrecargar. Desde C++20 , el operador de desigualdad se genera automáticamente si operator==
se define y los cuatro operadores relacionales se generan automáticamente si operator<=>
se define. [1]
Todos los operadores lógicos existen en C y C++ y pueden sobrecargarse en C++, aunque no se recomienda la sobrecarga de los operadores lógicos AND y OR, porque como operadores sobrecargados se comportan como llamadas de función ordinarias, lo que significa que ambos operandos se evalúan, por lo que pierden su propiedad de evaluación de cortocircuito, tan utilizada y esperada . [2]
Todos los operadores bit a bit existen en C y C++ y pueden sobrecargarse en C++.
Todas las expresiones de asignación existen en C y C++ y pueden sobrecargarse en C++.
Para los operadores dados, la semántica de la expresión de asignación combinada incorporada a ⊚= b
es equivalente a a = a ⊚ b
, excepto que a
se evalúa solo una vez.
Notas:
<<
y >>
como los operadores "put-to" o "inserción de flujo" y "get-from" o "extracción de flujo", respectivamente.operator &
se puede obtener con std::addressofoperator->()
->
x
C
C
operator->()
x->y
x.operator->()->y
::
signo de puntuación en C a partir de C23, no se utiliza como operador de resolución de alcance.alignof
el operador, mientras que C define _Alignof
(C23 define ambos). Ambos operadores tienen la misma semántica.new auto
) si se proporciona un inicializador.La siguiente es una tabla que enumera la precedencia y asociatividad de todos los operadores en los lenguajes C y C++ . Los operadores se enumeran de arriba a abajo, en orden de precedencia descendente. La precedencia descendente se refiere a la prioridad de la agrupación de operadores y operandos. Considerando una expresión, un operador que está enumerado en alguna fila se agrupará antes que cualquier operador que esté enumerado en una fila más abajo. Los operadores que están en la misma celda (puede haber varias filas de operadores enumerados en una celda) se agrupan con la misma precedencia, en la dirección dada. La precedencia de un operador no se ve afectada por la sobrecarga.
La sintaxis de las expresiones en C y C++ se especifica mediante una gramática de estructura de frase . [7] La tabla que se proporciona aquí se ha inferido de la gramática. [ cita requerida ] Para el estándar ISO C 1999, la nota 71 de la sección 6.5.6 establece que la gramática de C proporcionada por la especificación define la precedencia de los operadores de C, y también establece que la precedencia de los operadores resultante de la gramática sigue de cerca el orden de las secciones de la especificación:
" La sintaxis [es decir, la gramática] [C] especifica la precedencia de los operadores en la evaluación de una expresión, que es la misma que el orden de las subcláusulas principales de esta subcláusula, la precedencia más alta primero". [8]
Una tabla de precedencia, aunque en su mayor parte es adecuada, no puede resolver algunos detalles. En particular, observe que el operador ternario permite cualquier expresión arbitraria como su operando intermedio, a pesar de estar listado como de mayor precedencia que los operadores de asignación y coma. Por lo tanto , a ? b, c : d
se interpreta como a ? (b, c) : d
, y no como el sin sentido (a ? b), (c : d)
. Por lo tanto, la expresión en el medio del operador condicional (entre ?
y :
) se analiza como si estuviera entre paréntesis. Además, observe que el resultado inmediato, sin paréntesis, de una expresión de conversión de C no puede ser el operando de sizeof
. Por lo tanto, sizeof (int) * x
se interpreta como (sizeof(int)) * x
y no como sizeof ((int) * x)
.
[9] [10] [11]
La tabla de precedencia determina el orden de enlace en expresiones encadenadas, cuando no se especifica expresamente mediante paréntesis.
++x*3
es ambiguo sin alguna regla de precedencia. La tabla de precedencia nos dice que: x está 'ligado' más estrechamente a ++ que a * , de modo que cualquier cosa que ++ haga (ahora o más tarde, ver más abajo), lo hace SÓLO a x (y no a ); es equivalente a ( , ).x*3
++x
x*3
3*x++
, donde aunque el sufijo ++ está diseñado para actuar DESPUÉS de que se evalúe toda la expresión, la tabla de precedencia deja en claro que SÓLO x se incrementa (y NO ). De hecho, la expresión ( , ) se evalúa con tmp como un valor temporal. Es funcionalmente equivalente a algo como ( , , ).3*x
tmp=x++
3*tmp
tmp=3*x
++x
tmp
A muchos de los operadores que contienen secuencias de múltiples caracteres se les asignan "nombres" construidos a partir del nombre del operador de cada carácter. Por ejemplo, +=
y -=
se suelen llamar plus equal(s) y minus equal(s) , en lugar de los más verbosos "asignación por adición" y "asignación por sustracción". La vinculación de operadores en C y C++ se especifica (en los estándares correspondientes) mediante una gramática de lenguaje factorizada, en lugar de una tabla de precedencia. Esto crea algunos conflictos sutiles. Por ejemplo, en C, la sintaxis para una expresión condicional es:
expresión lógica - OR - expresión ? expresión : expresión condicional
Mientras que en C++ es:
expresión lógica - OR - expresión ? expresión : asignación - expresión
De ahí la expresión:
e = a < d ? a++ : a = d
se analiza de forma diferente en los dos lenguajes. En C, esta expresión es un error de sintaxis, porque la sintaxis para una expresión de asignación en C es:
unario - expresión '=' asignación - expresión
En C++, se analiza como:
e = ( a < d ? a ++ : ( a = d ))
lo cual es una expresión válida. [12] [13]
Si desea utilizar una coma como operador dentro de un único argumento de función, asignación de variable u otra lista separada por comas, debe utilizar paréntesis, [14] [15] por ejemplo:
int a = 1 , b = 2 , variableRara = ( ++ a , b ), d = 4 ;
Se ha criticado la precedencia de los operadores lógicos bit a bit. [16] Conceptualmente, & y | son operadores aritméticos como * y +.
La expresión se analiza sintácticamente como mientras que la expresión se analiza como . Esto requiere que los paréntesis se utilicen con más frecuencia de lo que se haría de otra manera.a & b == 7
a & (b == 7)
a + b == 7
(a + b) == 7
Históricamente, no había distinción sintáctica entre los operadores lógicos y de bits. En BCPL , B y principios de C, los operadores no existían. En cambio, tenían un significado diferente según se usaran en un "contexto de valor verdadero" (es decir, cuando se esperaba un valor booleano, por ejemplo, en se comportaba como un operador lógico, pero en se comportaba como un operador de bits). Se mantuvo para mantener la compatibilidad con versiones anteriores de las instalaciones existentes. [17]&& ||
& |
if (a==b & c) {...}
c = a & b
Además, en C++ (y versiones posteriores de C) las operaciones de igualdad, con la excepción del operador de comparación de tres vías, producen valores de tipo bool que conceptualmente son un solo bit (1 o 0) y, como tales, no pertenecen propiamente a operaciones "bit a bit".
C++ define [18] ciertas palabras clave que actúan como alias para varios operadores:
Estos pueden usarse exactamente de la misma manera que los símbolos de puntuación que reemplazan, ya que no son el mismo operador bajo un nombre diferente, sino más bien simples reemplazos de tokens para el nombre (cadena de caracteres) del operador respectivo. Esto significa que las expresiones (a > 0 and not flag)
y (a > 0 && !flag)
tienen significados idénticos. También significa que, por ejemplo, la bitand
palabra clave puede usarse para reemplazar no solo al operador y bit a bit sino también al operador de dirección de , e incluso puede usarse para especificar tipos de referencia (por ejemplo, int bitand ref = n
). La especificación ISO C permite estas palabras clave como macros de preprocesador en el archivo de encabezado iso646.h
. Para compatibilidad con C, C++ también proporciona el encabezado iso646.h
, cuya inclusión no tiene efecto. Hasta C++20, también proporcionaba el encabezado correspondiente ciso646
que tampoco tenía efecto.