Expressões
Diogo Silva
CAP / ENGEL
dasilva@academiafa.edu.pt
O que são?
Expressões devolvem sempre um valor concreto com um determinado tipo.
Operações aritméticas
1+2 // soma
3.14-2 // subtração
1*2.3 // multiplicação
5/2 // divisão, devolve 2 -> porquê?
5%2 // resto da divisão
int v = 2;
-v // torna valor negativo, operação unária
–
Operação unária? Operação que recebe apenas 1 operando.
Por outro lado, as outras operações são binárias (2 operandos).
–
⚠️ Cuidado com a divisão! ⚠️
O operador para a divisão, quando recebe 2 operandos inteiros, devolve sempre um valor inteiro (ignorando, sem arredondamento, a parte decimal)
Quando misturamos um inteiro com um real, o inteiro é automaticamente convertido e o resultado será o valor preciso
–
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.
Precedência e associatividade
1+2*-2
É o tipo de expressão que não devem escrever. Devem usar () para melhorar legibilidade.
Mas se vissem esta expressão, qual seria o resultado?
–
As operações no C têm uma precedência.
Precedência | Operadores |
---|---|
Alta | + - unários (e.g. -2) |
--- |
* / % |
Baixa | + - |
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?
i - j + k
i / j * k
–
Tem-se em conta a associatividade.
i - j + k == (i - j) + k
i / j * k == (i / j) * k
+ - * / %
têm associtividade à esquerda, o que quer dizer que agrupam o que está antes do operador.
Os operadores unários têm associatividade à direita.
- -2 == - (-2)
Operadores de atribuição
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
Não é equivalente a v = v * 3 + 10
. Esta expressão, deviso às regras de precedência a associatividade iria dar um resultado diferente.
–
Não confundir +=
com =+
.
A primeira operação acumula o valor à direita.
A segunda atribui o valor que a variável já tem.
–
Posto isto, usem sempre ( ) para deixar claro qual é a ordem das operações.
Incremento e decremento
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-incremneto).
Qual será a diferença?
int i=10;
printf("%d\n", ++i); // ?
printf("%d\n", i); // ?
i=10;
printf("%d\n", i++); // ?
printf("%d\n", i); // ?
–
int i=10;
printf("%d\n", ++i); // 11
printf("%d\n", i); // 11
i=10;
printf("%d\n", i++); // 10
printf("%d\n", i); // 11
–
Além do incremento ++
, também temos disponível o decremento --
, que funciona da mesma forma, mas subtrai em uma unidade.
Avaliação de expressões
Resumo das operações que já vimos:
postfix == pós-incremento
prefix == pré-incremento
–
Com este conhecimento conseguimos avaliar expressões complicadas.
a= b += c++ - d + --e / -f
- Encontrar o operador com maior precedência.
- Colocar ( ) à volta do operador e operandos.
- Aplicar regras de precedência e associatividade.
- Repetir.
–
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))
e depois o + (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)
(a= (b += (((c++) - d) + ((--e) / (-f)))))