Articulo de referencia

Operadores en C y C++

Esta es una lista de operadores en los lenguajes de programación C y C++ . Todos los operadores listados están en C++ y, a menos que se indique lo contrario, también en C. Algun...

Esta es una lista de operadores en los lenguajes de programación C y C++ .

Todos los operadores listados están en C++ y, a menos que se indique lo contrario, también en C. Algunas tablas incluyen una columna "En C" que indica si un operador también está en C. Tenga en cuenta que C no admite la sobrecarga de operadores .

Cuando no están sobrecargados, para los operadores &&, ||, y ,(el operador coma ), hay un punto de secuencia después de la evaluación del primer operando.

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.

Muchos operadores, especificados mediante una secuencia de símbolos, suelen denominarse con un nombre que consiste en el nombre de cada símbolo. Por ejemplo, +=y -=se suelen llamar "suma igual" y "resta igual", en lugar de los términos más extensos "asignación por suma" y "asignación por resta".

Operadores

En las siguientes tablas, las letras minúsculas como ay brepresentan valores literales, nombres de objetos/variables o valores l, según corresponda. R, Sy Trepresentan un tipo de dato, y Kun tipo de clase o enumeración. Algunos operadores tienen ortografías alternativas usando dígrafos y trígrafos o sinónimos de operador .

Aritmética

C y C++ tienen los mismos operadores aritméticos y todos ellos se pueden sobrecargar en C++.

Relacional

Todos los operadores relacionales (de comparación) pueden sobrecargarse en C++. Desde C++20 , el operador de desigualdad se genera automáticamente si operator==está definido y los cuatro operadores relacionales se generan automáticamente si operator<=>está definido. [ 1 ]

Lógico

C y C++ tienen los mismos operadores lógicos y todos ellos se pueden sobrecargar en C++.

Tenga en cuenta que no se recomienda sobrecargar los operadores lógicos AND y OR , ya que, al estar sobrecargados, siempre evalúan ambos operandos en lugar de proporcionar la semántica normal de evaluación en cortocircuito . [ 2 ]

Bitwise

C y C++ tienen los mismos operadores bit a bit y todos ellos se pueden sobrecargar en C++.

Asignación

C y C++ tienen los mismos operadores de asignación y todos ellos se pueden sobrecargar en C++.

Para los operadores de combinación, a ⊚= b(donde representa una operación) es equivalente a a = a ⊚ b, excepto que ase evalúa solo una vez.

Miembro y puntero

Otro

Sinónimos

C++ define palabras clave para actuar como alias de varios operadores: [ 7 ]

Cada palabra clave es una forma diferente de especificar un operador y, como tal, puede usarse en lugar de la variación simbólica correspondiente. Por ejemplo, (a > 0 and not flag)y (a > 0 && !flag)especifican el mismo comportamiento. Como otro ejemplo, la bitandpalabra clave puede usarse para reemplazar no solo el operador AND bit a bit, sino también el operador de dirección de , y puede usarse para especificar tipos de referencia (por ejemplo, int bitand ref = n).

La especificación ISO C permite el uso de estas palabras clave como macros de preprocesador en el archivo de cabecera iso646.h. Para garantizar la compatibilidad con C, C++ también proporciona la cabecera iso646.h, cuya inclusión no tiene ningún efecto. Hasta C++20, también proporcionaba la cabecera correspondiente ciso646, que tampoco tenía ningún efecto.

Orden de evaluación de la expresión

Durante la evaluación de expresiones, el orden en que se evalúan las subexpresiones viene determinado por la precedencia y la asociatividad . Un operador con mayor precedencia se evalúa antes que uno de menor precedencia, y los operandos de un operador se evalúan en función de la asociatividad. La siguiente tabla describe la precedencia y la asociatividad de los operadores de C y C++. Los operadores se muestran en grupos de igual precedencia, ordenados de arriba abajo en orden descendente (a menor orden, mayor precedencia). [ 8 ] [ 9 ] [ 10 ]

La precedencia de los operadores no se ve afectada por la sobrecarga.

Detalles

Aunque esta tabla es adecuada para describir la mayoría del orden de evaluación, no describe algunos detalles. El operador ternario permite cualquier expresión arbitraria como su operando medio, a pesar de figurar con mayor precedencia que los operadores de asignación y coma. Por lo tanto, se interpreta como , y no como el sin sentido . Así, la expresión en medio del operador condicional (entre y ) se analiza como si estuviera entre paréntesis. Además, el resultado inmediato, sin paréntesis, de una expresión de conversión de C no puede ser el operando de . Por lo tanto, se interpreta como y no .a ? b, c : da ? (b, c) : d(a ? b), (c : d)?:sizeofsizeof (int) * x(sizeof(int)) * xsizeof ((int) * x)

expresiones encadenadas

La tabla de precedencia determina el orden de vinculación en expresiones encadenadas, cuando no se especifica expresamente entre paréntesis.

  • Por ejemplo, ++x*3es ambiguo sin alguna regla de precedencia. La tabla de precedencia nos dice que: x está más estrechamente "vinculado" a ++ que a * , de modo que lo que sea que haga ++ (ahora o después, véase más abajo), lo hace SOLO sobre x (y no sobre ); es equivalente a ( , ).x*3++xx*3
  • De manera similar, con 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 claro que SOLO 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*xtmp=x++3*tmptmp=3*x++xtmp
Precedencia y vinculación
  • Abstraer el problema de precedencia o enlace, considere el diagrama anterior para la expresión 3+2*y[i]++. El trabajo del compilador es resolver el diagrama en una expresión, una en la que varios operadores unarios (llamémoslos 3+( . ), 2*( . ), ( . )++ y ( . )[ i ]) compiten para enlazarse a y. El orden de la tabla de precedencia resuelve la subexpresión final sobre la que actúa cada uno: ( . )[ i ] actúa solo sobre y, ( . )++ actúa solo sobre y[i], 2*( . ) actúa solo sobre y[i]++ y 3+( . ) actúa 'solo' sobre 2*((y[i])++). QUÉ subexpresión es actuada por cada operador está claro a partir de la tabla de precedencia, pero CUÁNDO actúa cada operador no está resuelto por la tabla de precedencia; En este ejemplo, el operador ( . )++ actúa solo sobre y[i] según las reglas de precedencia, pero los niveles de enlace por sí solos no indican el momento del sufijo ++ (el operador ( . )++ actúa solo después de que y[i] se evalúa en la expresión).

Vinculante

La vinculación de operadores en C y C++ se especifica 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 : expresión de asignación

Por lo tanto, 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:

unaria - expresión '=' asignación - expresión

En C++, se analiza como:

e = ( a < d ? a ++ : ( a = d ))

que es una expresión válida. [ 11 ] [ 12 ]

Para usar el operador coma en una expresión de argumento de llamada a función, asignación de variable o una lista separada por comas, se requiere el uso de paréntesis. [ 13 ] [ 14 ] Por ejemplo,

int a = 1 , b = 2 , weirdVariable = ( ++ a , b ), d = 4 ;

Críticas a la precedencia de los operadores bit a bit y de igualdad

Se ha criticado la precedencia de los operadores lógicos bit a bit. [ 15 ] 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 se utilicen paréntesis con más frecuencia de lo que se haría normalmente.a&b==7a&(b==7)a+b==7(a+b)==7

Históricamente, no existía una distinción sintáctica entre los operadores lógicos y los operadores bit a bit. En BCPL , B y las primeras versiones de C, estos operadores no existían. En cambio, tenían un significado diferente según se utilizaran en un contexto de valor de verdad (es decir, cuando se esperaba un valor booleano; por ejemplo, en se comportaban como un operador lógico, pero en se comportaban como uno bit a bit). Se mantuvo esta distinción para conservar la compatibilidad con versiones anteriores de las instalaciones existentes. [ 16 ]&&||&|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 booleano que conceptualmente son un solo bit (1 o 0) y, como tales, no pertenecen propiamente a las operaciones "bit-wise".

Notas

  1. El operador módulo solo admite operandos enteros; para números de punto flotante, se puede utilizaruna función como estafmod
  2. 1 2 3 4 Esteintes un parámetro ficticio para diferenciar entre prefijo y sufijo.
  3. Acerca de la comparación de tres vías en C++20
  4. Posibles tipos de retorno:ystd::weak_orderingalos que todos son convertibles.std::strong_orderingstd::partial_ordering
  5. 1 2 En el contexto de iostreams en C++, los escritores a menudo se referirán a<<y>>como los operadores "put-to" o "inserción de flujo" y "get-from" o "extracción de flujo", respectivamente.
  6. Según el estándar C99, el desplazamiento a la derecha de un número negativo depende de la implementación. La mayoría de las implementaciones, por ejemplo, GCC, [ 3 ] utilizan un desplazamiento aritmético (es decir, extensión de signo), pero es posible un desplazamiento lógico .
  7. Según el estándar C99, el desplazamiento a la derecha de un número negativo depende de la implementación. La mayoría de las implementaciones, por ejemplo, GCC, [ 3 ] utilizan un desplazamiento aritmético (es decir, extensión de signo), pero es posible un desplazamiento lógico .
  8. 1 2 3 desde C++23
  9. La dirección real de un objeto con una sobrecargaoperator &se puede obtener constd::addressof
  10. El tipo de retorno dedebe ser un tipo para el cualse pueda aplicar la operación, como un tipo de puntero. Sies de tipodondesobrecarga,se expande a.operator->()->xCCoperator->()x->yx.operator->()->y
  11. Meyers, Scott (octubre de 1999), "Implementación del operador -> * para punteros inteligentes" (PDF) , Dr. Dobb's Journal , Aristeia.
  12. Aunque::en C existe un signo de puntuación desde la versión C23, no se utiliza como operador de resolución de ámbito.
  13. Acerca de los literales definidos por el usuario en C++11
  14. 1 2 3 4 5 6 7 desde C++11
  15. Los paréntesis no son necesarios al tomar el tamaño de un valor, solo al tomar el tamaño de un tipo. Sin embargo, generalmente se usan de todos modos.
  16. C++ definealignofel operador, mientras que C define_Alignof(C23 define ambos). Ambos operadores tienen la misma semántica.
  17. desde C23; no está en C++ estándar
  18. Se comporta como const_cast/static_cast/reinterpret_cast. En los dos últimos casos, elautoespecificador se reemplaza con el tipo de la variable inventada x declarada conauto x(a);(que nunca se interpreta como una declaración de función) oauto x{a};, respectivamente.
  19. Para conversiones definidas por el usuario, el tipo de retorno coincide implícita y necesariamente con el nombre del operador, a menos que el tipo se infiera (por ejemplo, ,etc.).operatorauto()operatordecltype(auto)()
  20. El nombre del tipo también se puede inferir (por ejemplonew auto) si se proporciona un inicializador.
  21. El tamaño del array también se puede inferir si se proporciona un inicializador.
  22. desde C++26

Véase también

  • Operaciones bit a bit en C : operaciones que transforman bits individuales de tipos de datos enteros. 
  • Manipulación de bits : modificación algorítmica de datos por debajo del nivel de palabra. 
  • Operador lógico : símbolo que conecta fórmulas en lógica. Páginas que muestran breves descripciones de destinos de redireccionamiento. 
  • Álgebra booleana (lógica) : manipulación algebraica de "verdadero" y "falso". Páginas que muestran breves descripciones de destinos de redirección. 
  • Tabla de símbolos lógicos : lista de símbolos utilizados para expresar relaciones lógicas. Páginas que muestran breves descripciones de destinos de redireccionamiento. 

Referencias

  1. "Sobrecarga de operadores§Operadores de comparación" . cppreference.com .
  2. "C++ estándar" .
  3. 1 2 "Implementación de enteros", GCC 4.3.3 , GNU.
  4. "Especificación ISO/IEC 9899:1999, TC3" (PDF) . pág. 64, § 6.4.6 Ponctuadores párr. 3.
  5. "conversión definida por el usuario" . Consultado el 5 de abril de 2020 .
  6. Conversión explícita de tipos en C++
  7. ISO/IEC 14882:1998(E) Lenguaje de programación C++ . open-std.org – Comité de estándares de C++. 1 de septiembre de 1998. págs. 40–41 . 
  8. ISO/IEC 9899:201x Lenguajes de programación - C . open-std.org – El Comité de Estándares C. 19 de diciembre de 2011. pág. 465. 
  9. la norma ISO C 1999, sección 6.5.6 nota 71 (Informe técnico). ISO. 1999.
  10. "Operadores integrados de C++, precedencia y asociatividad" . docs.microsoft.com . Consultado el 11 de mayo de 2020 .
  11. "Precedencia de operadores en C - cppreference.com" . en.cppreference.com . Consultado el 10 de abril de 2020 .
  12. "¿Tiene el operador ternario de C/C++ la misma precedencia que los operadores de asignación?" . Stack Overflow . Consultado el 22 de septiembre de 2019 .
  13. "Otros operadores - cppreference.com" . en.cppreference.com . Consultado el 10 de abril de 2020 .
  14. "c++ - ¿Cómo funciona el operador coma?" . Stack Overflow . Consultado el 1 de abril de 2020 .
  15. Historia de la C § C neonatal , Laboratorios Bell.
  16. "Re^10: siguiente condición a menos que" . www.perlmonks.org . Consultado el 23 de marzo de 2018 .
  • "Operadores", referencia de C++ (wiki).
  • Precedencia del operador C
  • Operadores de incremento y decremento posfijo: ++ y -- (Red de desarrolladores), Microsoft, 17 de agosto de 2021.