Operadores y expresiones en C++: Guía completa

En C++, los operadores son símbolos que permiten manipular datos (+, -, *, entre otros), mientras que las expresiones combinan operadores, operandos y paréntesis para producir un resultado. Dominar la precedencia, la asociatividad y los efectos secundarios es esencial para escribir código robusto.

Clasificación de operadores

1. Operadores aritméticos
  • Operaciones básicas: + (suma), - (resta), * (multiplicación), / (división), % (módulo, solo enteros).
  • Consideraciones clave:
  • La división entre enteros descarta la parte decimal (7/2 da 3). Para preservarla, usa al menos un operando flotante (7.0/2).
  • El signo del módulo x%y coincide con el de x (-7%3 resulta en -1).
2. Operadores de asignación
  • Asignación simple: = (ejemplo: int valor = 42;).
  • Asignación compuesta: +=, -=, *=, /=, %= (ejemplo: valor *= 3 equivale a valor = valor * 3).
3. Operadores relacionales
  • Devuelven un valor booleano (true o false): ==, !=, >, <, >=, <=.
4. Operadores lógicos
  • Evaluación de cortocircuito:
  • && (AND lógico): solo es true si ambos operandos son verdaderos.
  • || (OR lógico): es true si al menos un operando es verdadero.
  • ! (NOT lógico): invierte el valor booleano.
  • Ejemplo: (x > 0) && (y < 100) — si x > 0 es false, la segunda condición no se evalúa.
5. Operadores a nivel de bits
  • Manipulan directamente los bits:
  • & (AND bit a bit), | (OR bit a bit), ^ (XOR bit a bit), ~ (NOT bit a bit).
  • << (desplazamiento a la izquierda), >> (desplazamiento a la derecha): n << 3 equivale a n * 8.
6. Operadores de incremento y decremento
  • Forma prefija (incrementa y luego usa el valor): ++contador, --contador.
  • Forma postfija (usa el valor y luego incrementa): contador++, contador--.
int contador = 10;
int primerValor = ++contador;  // contador=11, primerValor=11
int segundoValor = contador++;   // contador=12, segundoValor=11

7. Operador condicional (ternario)
  • Sintaxis: condición ? expresiónVerdadera : expresiónFalsa.
  • Ejemplo: int mayorValor = (x > y) ? x : y;
8. Otros operadores relevantes
  • Acceso a miembros: . (objeto), -> (puntero).
  • Memoria: & (dirección de), * (desreferencia).
  • Conversión de tipos: static_cast, dynamic_cast, const_cast, reinterpret_cast.
  • Operador coma: , evalúa de izqiuerda a derecha y retorna el último valor.

Precedencia y asociatividad

1. Reglas de precedencia
  • Máxima precedencia: paréntesis (), acceso a miembros ./->, incremento/decremento postfijo.
  • Precedencia media: operadores aritméticos (*, /, % antes que +, -), operadores relacionales.
  • Baja precedencia: operadores lógicos (&& antes que ||), operadores de asignación.
  • Ejemplo: x + y * z se evalúa como x + (y * z).
2. Asociatividad
  • Asociatividad por la izquierda: la mayoría de operadores (x - y - z equivale a (x - y) - z).
  • Asociatividad por la derecha: operadores de asignación (x = y = z equivale a x = (y = z)).

Expresiones y efectos secundarios

1. Evaluación de expresiones
  • Las expresiones pueden anidarse y se evalúan según precedencia y asociatividad:
int resultadoFinal = (x + y) * z / w;  // Primero paréntesis, luego de izquierda a derecha

2. Efectos secundarios
  • Definición: modificaciones persistentes tras evaluar una expresión (asignación, incremento).
  • Advertencia: evitar múltiples modificaciones a la misma variable en una sola expresión, ya que el comportamiento no está definido:
int numero = 8;
int suma = (numero++) + (++numero);  // Comportamiento indefinido: el resultado varía según el compilador

Errores comunes y recomendaciones

1. Truncado en división de enteros
  • Incorrecto: float proporcion = 3/2; (resultado 1.0 por división entera).
  • Correcto: float proporcion = 3.0/2; o float proporcion = static_cast<float>(3)/2;.
2. Aprovechamiento del cortocircuito lógico
  • Uso seguro para evitar acceso a punteros nulos:
if (puntero != nullptr && puntero->dato > 0) { /* ... */ }

3. Distinción entre operadores bit a bit y lógicos
  • x & y realiza AND bit a bit (6 & 3 da 2).
  • x && y realiza AND lógico (6 && 3 da true).

Técnicas avanzadas

1. Optimización con operaciones bit a bit
  • Verificar paridad: if (numero & 1) { /* impar */ }.
  • Intercambio sin variable temporal: x ^= y; y ^= x; x ^= y;.
2. Simplificación con operador ternario
// En lugar de:
if (x > y) mayorValor = x;
else mayorValor = y;

// Usar:
mayorValor = (x > y) ? x : y;

Etiquetas: C++ operadores expresiones precedencia bit-a-bit

Publicado el 8-2 10:38