Precedência e ordem da avaliação
A precedência e a associatividade dos operadores C afetam o agrupamento e a avaliação dos operandos nas expressões. A precedência de um operador é significante somente quando outros operadores com precedência maior ou menor estão presentes. As expressões com operadores de maior precedência são avaliadas primeiro. A precedência também pode ser descrita pela palavra “associação”. Os operadores com maior precedência são ditos ter uma associação mais próxima.
A tabela a seguir resume a precedência e a associatividade (a ordem em que os operandos são avaliados) dos operadores C, listando-os em ordem decrescente de precedência. Onde vários operadores aparecem juntos, eles têm a mesma precedência e são avaliados de acordo com sua associatividade. Os operadores na tabela são descritos nas seções que começam com Operadores de sufixo. O restante desta seção fornece informações gerais sobre a precedência e associatividade.
Precedência e associatividade de operadores C
Symbol1 |
Tipo de operação |
Associatividade |
---|---|---|
[ ] ( ) . –> sufixo ++ e sufixo –– |
Expressão |
Da esquerda para a direita |
prefixo ++ e prefixo –– sizeof & * + – ~ ! |
Unário |
Da direita para a esquerda |
typecasts |
Unário |
Da direita para a esquerda |
* / % |
Multiplicativo |
Da esquerda para a direita |
+ – |
Aditivo |
Da esquerda para a direita |
<< >> |
Deslocamento bit a bit |
Da esquerda para a direita |
< > <= >= |
Relacional |
Da esquerda para a direita |
== != |
Igualdade |
Da esquerda para a direita |
& |
Bitwise-AND |
Da esquerda para a direita |
^ |
Bitwise-exclusive-OR |
Da esquerda para a direita |
| |
Bitwise-inclusive-OR |
Da esquerda para a direita |
&& |
Logical-AND |
Da esquerda para a direita |
|| |
Logical-OR |
Da esquerda para a direita |
? : |
Expressão condicional |
Da direita para a esquerda |
= *= /= %= += –= <<= >>=&= ^= |= |
Atribuição simples e composta2 |
Da direita para a esquerda |
, |
Avaliação sequencial |
Da esquerda para a direita |
1. Os operadores são listados em ordem decrescente de precedência. Quando vários operadores aparecem na mesma linha ou em um grupo, eles têm a mesma precedência.
2. Todos os operadores de atribuição simples e composta têm a mesma precedência.
Uma expressão pode conter vários operadores com a mesma precedência. Quando vários desses operadores aparecem no mesmo nível em uma expressão, a avaliação procede de acordo com a associatividade do operador, da direita para a esquerda ou da esquerda para a direita. A direção da avaliação não afeta os resultados das expressões que incluem mais de um operador de multiplicação (*), adição (+) ou binário bit a bit (& | ^) no mesmo nível. A ordem das operações não é definida pela linguagem. O compilador é livre para avaliar essas expressões em qualquer ordem, se ele puder garantir um resultado consistente.
Somente os operadores de avaliação sequencial (,), AND lógico (&&), OR lógico (||), de expressão condicional (? :) e de chamada de função constituem pontos de sequência e, portanto, garantem uma ordem específica de avaliação de seus operandos. O operador da chamada de função é o conjunto de parênteses depois do identificador da função. O operador de avaliação sequencial (,) é garantido para avaliar seus operandos da esquerda para a direita. (Observe que o operador vírgula em uma chamada de função não é o mesmo que o operador de avaliação sequencial e não fornece tal garantia.) Para obter mais informações, consulte Pontos de sequência.
Os operadores lógicos também garantem a avaliação de seus operandos da esquerda para a direita. No entanto, eles avaliam o menor número de operandos necessários para determinar o resultado da expressão. Isso é chamado de avaliação de" curto-circuito". Assim, alguns operandos da expressão não podem ser avaliados. Por exemplo, na expressão
x && y++
o segundo operando, y++, será avaliado somente se x for true (diferente de zero). Assim, y não será incrementado se x for false (0).
Exemplos
A lista a seguir mostra como o compilador associa automaticamente várias expressões de exemplo:
Expressão |
Associação automática |
---|---|
a & b || c |
(a & b) || c |
a = b || c |
a = (b || c) |
q && r || s-- |
(q && r) || s–– |
Na primeira expressão, o operador AND bit a bit (&) tem uma maior precedência que o operador OR lógico (||), então a & b forma o primeiro operando da operação OR lógica.
Na segunda expressão, o operador OR lógico (||) tem maior precedência que o operador de atribuição simples (=), então b || c é agrupado como o operando à direita na atribuição. Observe que o valor atribuído a a é 0 ou 1.
A terceira expressão mostra uma expressão corretamente formada que pode gerar um resultado inesperado. O operador AND lógico (&&) tem maior precedência que o operador OR lógico (||), então q && r é agrupado como um operando. Como os operadores lógicos garantem a avaliação dos operandos da esquerda para a direita, q && r é avaliado antes de s––. No entanto, se q && r for avaliado como um valor diferente de zero, s–– não será avaliado, e s não será diminuído. Se não diminuir s for causar um problema em seu programa, s–– deverá aparecer como o primeiro operando da expressão, ou s deverá ser diminuído em uma operação separada.
A expressão a seguir é ilegal e gera uma mensagem de diagnóstico no tempo de compilação:
Expressão ilegal |
Agrupamento padrão |
---|---|
p == 0 ? p += 1: p += 2 |
( p == 0 ? p += 1 : p ) += 2 |
Nessa expressão, o operador de igualdade (==) tem a precedência mais alta, então p == 0 é agrupado como um operando. O operador de expressão condicional (? :) tem a próxima precedência mais alta. Seu primeiro operando é p == 0, e o segundo operando é p += 1. No entanto, o último operando do operador de expressão condicional é considerado p em vez de p += 2, já que essa ocorrência de p se associa ainda mais ao operador de expressão condicional do que ao operador de atribuição composta. Um erro de sintaxe ocorre porque += 2 não tem um operando à esquerda. Você deve usar parênteses para evitar erros desse tipo e gerar um código mais legível. Por exemplo, você pode usar parênteses como mostrado abaixo para corrigir e esclarecer o exemplo anterior:
( p == 0 ) ? ( p += 1 ) : ( p += 2 )