Expressões

Operadores aritméticos

adição a+b
subtração a-b
multiplicação a*b
divisão a/b
resto da divisão a%b
menos unário -a
mais unário +a

Operadores aritméticos unários

    i = +1;
    j = -i;

Operadores aritméticos binários

Divisão inteira

Cuidados com / e %

Precedência de operadores

Precedência de operadores

  1. Primeiro é avaliados + e - unários
  2. Depois *, /, %
  3. Por fim + e - binários

Exemplos

i + j * k equivalente a i + (j*k)
-i * -j equivalente a (-i) * (-j)
+ i + j/k equivalente a (+i) + (j/k)

Associatividade de operadores

Exemplos

i - j - k equivale a (i - j) - k
i * j / k equivale a (i * j) / k
- + j equivale a -(+j)

Atribuição simples

    i = 5;            /* valor de i: 5  */
    j = i;            /* valor de j: 5  */
    k = 10 * i + j;   /* valor de k: 55 */

Atribuição simples (cont.)

Se a variável e expressão não forem do mesmo tipo dá-se uma conversão implícita de tipos.

   int i;
   float f;
    
   i = 72.99;   // valor de i: 72 
   f = 136;     // valor de f: 136.0 

Atribuições são expressões

Exemplo:

int i, j, k;
i = 1;
k = 1 + (j = i);
   // j: 1, k: 2

Cuidado: usar atribuições no meio de expressões pode dificultar a compreensão de programas

Atribuições em sequência

Podemos atribuir um mesmo valor a várias variáveis:

i = j = k = 0;

Como a atribuição associa à direita, isto é equivalente a:

i = (j = (k = 0));

Valores esquerdos (Lvalues)

i = 12;    // OK: i é um lvalue
12 = i;    // erro: 12 não é um lvalue
1+j = 12;  // erro: 1+j não é um lvalue

Atribuição composta

É frequente atribuir a uma variável um novo valor que depende do seu valor atual.

Exemplo:

i = i + 2;

Nestes casos podemos usar uma atribuição composta:

i += 2;

Operadores de atribuição composta

\(v\) += \(e\)

adicionar \(e\) de \(v\), guardando o resultado em \(v\)

\(v\) -= \(e\)

subtrair \(e\) a \(v\), guardando o resultado em \(v\)

\(v\) *= \(e\)

multiplicar \(e\) por \(v\), guardando o resultado em \(v\)

\(v\) /= \(e\)

dividir \(v\) por \(e\), guardando o resultado em \(v\)

\(v\) %= \(e\)

calcular o resto de divisão de \(v\) por \(e\), guardando o resultado em \(v\)

Incremento e decremento

É frequente somar ou subtrair uma variável inteira de uma unidade.

i = i + 1;
j = j - 1;

Também aqui podemos usar uma atribuição composta:

i += 1;
j -= 1;

Em alternativa, podemos usar operadores de incremento ou decremento.

Incremento e decremento (cont.)

++i;        // equivalente a i = i + 1
--j;        // equivalente a j = j - 1

Pré- e pós-incremento

++i modifica a variável i (incrementa de uma unidade) e dá o valor resultante.

i = 1;
printf("%d\n", ++i);  // imprime 2
printf("%d\n", i);    // imprime 2

i++ dá o valor atual de i e depois modifica a variável i (incrementa de 1 unidade).

i = 1;
printf("%d\n", i++);  // imprime 1
printf("%d\n", i);    // imprime 2

Pré- e pós-incremento

Pré- e pós-decremento

O operador de decremento comporta-se de forma análoga ao de incremento:

i = 1;
printf("%d\n", --i);  // imprime 0
printf("%d\n", i);    // imprime 0
i = 1;
printf("%d\n", i--);  // imprime 1
printf("%d\n", i);    // imprime 0

Incremento e decremento

Pode ser difícil seguir o efeito de múltiplos ++ ou -- em várias variáveis numa mesma expressão:

i = 1;
j = 2;
k = ++i + j++;
 // i: 2, j: 3, k: 4
i = 1;
j = 2;
k = i++ + j++;
 // i: 2, j: 3, k: 3

Recomendação: evite expressões com mútiplos incrementos.

Ordem de avaliação

a = 5;
c = (b = a + 2) - (a = 1);

Qual é o valor final de c?

Logo: o comportamento deste programa depende da ordem de avaliação das subexpressões.

Ordem de avaliação

Outro exemplo

i = 2;
j = i * i++;

O resultado final de j depende da ordem de avaliação da multiplicação (4 ou 6).

Comportamento indefinido

       gcc -Wall -o programa programa.c

Comportamento indefinido

Re-escrever o primeiro exemplo para evitar comportamento indefinido:

a = 5;
b = a + 2;
a = 1;
c = b - a;

Desta forma o resultado final de c é sempre 6.