Expressões
Slides
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, e.g. -v
Por outro lado, as outras operações são binárias ➡ 2 operandos, e.g. 1+2
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
Qual o valor desta expressão?
1+2*-2
Evitem escrever expressões deste tipo. Usem
( )
para melhorar legibilidade.Melhor?
1 + (2 * -2)
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 |
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?
- j + k
i
/ j * k i
Tem-se em conta a associatividade.
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)
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 av = v * 3
, embora na maior parte das utilizações o resultado seja o mesmo. Porquê?Observem a expressão
v *= 3 + 10
. É equivalente av = 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.
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-incremento).
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
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
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 comumd
(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 ( )
.