Menu

Operadores em C++: aritméticos, de comparação, lógicos e mais

Aprenda os operadores de C++ - aritméticos, de comparação, lógicos, de atribuição e bit a bit - além das armadilhas da divisão inteira, da precedência e do curto-circuito.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

O que os operadores fazem

Um operador é um símbolo que realiza uma ação sobre um ou mais valores, chamados operandos. Você já vem usando um: o = que liga um valor a uma variável. C++ vem com um conjunto rico de operadores para matemática, comparação, lógica e manipulação de bits - e algumas arestas afiadas que pegam os iniciantes de surpresa.

Na página anterior você viu como const trava um valor. Os operadores são a forma de calcular os valores que você armazena, sejam eles constantes ou não. Vamos percorrer as famílias que você usará todos os dias.

Operadores aritméticos

Os cinco operadores aritméticos são +, -, *, / e % (módulo, o resto de uma divisão):

A grande armadilha vive nesse quociente. 17 / 5 imprime 3, não 3.4. Quando ambos os operandos são inteiros, / faz divisão inteira e descarta a parte fracionária - ele trunca em direção a zero, não arredonda. Se você quer uma fração real, pelo menos um operando precisa ser de ponto flutuante:

O operador % só funciona com inteiros. Usar % em um double é um erro de compilação - use std::fmod de <cmath> para restos de ponto flutuante.

Atribuição e operadores compostos

Um único = atribui; ele não compara. C++ oferece formas compostas que combinam uma operação com a atribuição para que você não precise repetir o nome da variável:

Um erro clássico e doloroso é escrever = onde você queria == dentro de uma condição. if (x = 0) atribui 0 a x e então testa o resultado (que é falso), em vez de comparar. Compiladores modernos avisam sobre isso quando você ativa os avisos - mantenha -Wall ligado e leve o aviso a sério.

Operadores de comparação

Os operadores de comparação fazem uma pergunta de sim/não e produzem um bool (true ou false):

Por padrão, cout imprime um bool como 1 ou 0. Insira boolalpha uma vez e ele passa a mostrar as palavras true/false no restante daquele fluxo.

Uma armadilha sutil: não encadeie comparações como 1 < x < 10. Isso é interpretado como (1 < x) < 10 - a primeira comparação produz um bool (0 ou 1), que é então comparado com 10, de modo que o resultado é quase sempre true. Escreva 1 < x && x < 10 em vez disso.

Operadores lógicos e curto-circuito

&& (e), || (ou) e ! (não) combinam expressões booleanas. Os dois primeiros fazem curto-circuito: a avaliação para assim que o resultado é conhecido.

Nem check("A") nem check("B") chegam a rodar - isso é o curto-circuito. Não é apenas uma otimização; é uma ferramenta. Você pode escrever com segurança if (ptr != nullptr && ptr->ready) porque a parte ptr->ready só é alcançada quando ptr não é nulo, evitando a desreferência de um ponteiro pendente.

Incremento e decremento

++ soma um; -- subtrai um. Cada um tem uma forma prefixa e uma posfixa, e a diferença importa quando você usa o resultado:

Quando você quer apenas o efeito colateral (em um laço for, por exemplo), prefira ++i. Para um int simples é idêntico, mas para tipos mais pesados como iteradores, o pós-incremento precisa copiar o valor antigo primeiro, o que é trabalho desperdiçado.

Mais um aviso: não modifique a mesma variável duas vezes em uma única expressão, como i = i++ + 1; ou arr[i] = i++;. A ordem dessas atualizações não é especificada e o resultado é comportamento indefinido. Mantenha cada variável com uma única modificação por instrução.

Operadores bit a bit e precedência

Para trabalho de baixo nível há os operadores bit a bit: & (e), | (ou), ^ (xor), ~ (não) e os deslocamentos << e >>.

Atenção: << e >> também são os operadores de fluxo em cout. Dentro de uma linha de cout, normalmente você precisa de parênteses ao redor de um deslocamento de bits, caso contrário o compilador o interpreta como uma inserção no fluxo.

Por fim, a precedência decide o que é avaliado primeiro quando você mistura operadores. * e / ligam mais forte do que + e -, assim como na matemática, então 2 + 3 * 4 é 14. A comparação liga mais fraco que a aritmética, e os lógicos &&/|| ainda mais fraco. Na dúvida, não memorize a tabela inteira - adicione parênteses. (a + b) * c é mais claro do que confiar que o leitor lembre das regras.

Próximo: conversão de tipos

Você viu acima que (double)a / b forçou um inteiro a entrar em uma divisão de ponto flutuante. Isso é uma conversão (cast) - converter deliberadamente um valor de um tipo para outro. Na próxima página vamos cobrir as ferramentas de conversão de C++, das promoções implícitas ao static_cast, e quando cada uma é segura.

Perguntas frequentes

Quais são os operadores em C++?

C++ agrupa os operadores em aritméticos (+ - * / %), de comparação (== != < > <= >=), lógicos (&& || !), de atribuição (= += -= ...), incremento/decremento (++ --) e bit a bit (& | ^ ~ << >>). Há também o ternário ?: e alguns outros, como sizeof.

Por que 5 / 2 é igual a 2 em C++?

Porque ambos os operandos são int, então / faz divisão inteira e a parte fracionária é descartada - não arredondada. Para obter 2.5, faça com que pelo menos um operando seja um valor de ponto flutuante: 5.0 / 2 ou 5 / 2.0.

Qual é a diferença entre ++i e i++ em C++?

Ambos somam 1 a i. ++i (pré-incremento) incrementa primeiro e devolve o novo valor; i++ (pós-incremento) devolve o valor antigo e depois incrementa. Quando você só se importa com o efeito colateral, prefira ++i.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR