Academia da Força Aérea
Expressões devolvem sempre um valor concreto com um determinado tipo.
Operação unária ➡ Operação que recebe apenas 1 operando, e.g. -v
Por outro lado, as outras operações são binárias ➡ 2 operandos, e.g. 1+2
Cuidado com a divisão!
O resto da divisão %
requer 2 operandos inteiros.
Usar 0 como o segundo operando da divisão /
ou resto da divisão %
, i.e. divisão por 0, gera comportamento não definido.
As operações no C têm uma precedência.
Precedência | Nome | Operadores | Associatividade |
---|---|---|---|
1 | incremento (sufixo) | ++ -- |
esquerda |
2 | incremento (prefixo) additivos unários |
++ -- + - |
direita |
3 | multiplicativos | * / % |
esquerda |
4 | aditivos binários | + - |
esquerda |
5 | desigualdades | < <= > >= |
esquerda |
6 | igualdades | == != |
esquerda |
7 | atribuição | = *= /= %= += -= |
direita |
Exemplo de precedência de operadores. Fonte: geeksforgeeks.org
Exemplos:
1 + 2 * -2
➡ 1 + (2 * (-2))
i + j * k
➡ i + (j * k)
-i * -j
➡ (-i) * (-j)
E quando uma expressão tem 2 operações com a mesma precedência?
Tem-se em conta a associatividade.
Exemplo de associatividade de operadores. Fonte: geeksforgeeks.org
i / j * k
== (i / j) * k
+ - * / %
têm associtividade à esquerda, logo agrupam o que está antes do operador.
Os operadores unários têm associatividade à direita.
- -2
== - (-2)
Exemplo de associatividade e precedência de operadores. Fonte: geeksforgeeks.org
Já conhecemos o operador de atribuição simples =
.
É o que designamos por uma operação com efeitos secundários, porque altera o estado dos operandos.
a = 2
altera o estado da variável a
porque o seu valor é agora 2.
Adicionalmente, a = 2
é uma expressão válida que devolve o valor que foi atribuido à variável
Todas as operações de atribuição exigem que o operando da esquerda seja uma variável.
Existem outros que se combinam com operações aritméticas.
Expressão | Descrição |
---|---|
var+=3 |
soma 3 ao valor de var e atribui o resultado a var |
var-=3 |
subtrai 3 ao valor de var e atribui o resultado a var |
var*=3 |
multiplica 3 com o valor de var e atribui o resultado a var |
var/=3 |
divide o valor de var por 3 e atribui o resultado a var |
var%=3 |
faz o resto da divisão entre var e 3 e atribui o resultado a var |
v*=3
não é equivalente a v = v * 3
, embora na maior parte das utilizações o resultado seja o mesmo. Porquê?
Observem a expressão v *= 3 + 10
. É equivalente a v = v * 3 + 10
?
Devido às regras de precedência e associatividade leva a um resultado diferente.
Não confundir +=
com =+
.
A primeira operação acumula o valor à direita.
A segunda é uma simples atribuição seguida do operador +
unário.
Em suma…
… usem sempre ( )
para deixar claro qual é a ordem das operações.
Existe uma instrução que é frequentemente usada no C (irão perceber porquê quando abordarmos ciclos):
Existe outra forma de escrever esta instrução, com o operador de incremento ++
Este operador pode ser usado tanto antes de uma variável (pré-incremento) como depois (pós-incremento).
Qual será a diferença?
Além do incremento ++
, também temos disponível o decremento --
, que funciona da mesma forma, mas subtrai em uma unidade.
Com este conhecimento conseguimos avaliar expressões complicadas.
a= b += c++ - d + --e / -f
a= b += c++ - d + --e / -f
a= b += (c++) - d + (--e) / -f
c++
e depois --e
(precedência)a= b += (c++) - d + (--e) / (-f)
operador unário -f
(precedência)a= b += (c++) - d + ((--e) / (-f))
divisão (precedência)a= b += (c++) - d + ((--e) / (-f))
a= b += ((c++) - d) + ((--e) / (-f))
-
e +
com a mesma precedência e com operando em comum d
(precedência), agrupam da esquerda para a direita, logo -
primeiro (associatividade)a= b += (((c++) - d) + ((--e) / (-f)))
+
(precedência)a= (b += (((c++) - d) + ((--e) / (-f))))
=
e +=
com mesma precedência (precedência), agrupam da direita para a esquerda, logo +=
primeiro (associatividade)(a= (b += (((c++) - d) + ((--e) / (-f)))))
sobra apenas o =
(precedência)Moral da história: façam um favor a vós próprios…
… e usem ( )
.
Programação