A questão é dupla: em primeiro lugar, é
char c = CHAR_MAX;
c += 1;
avaliado diferentemente de
char c = CHAR_MAX;
c = c + 1;
e a resposta é não, não é , porque C11 / C18 6.5.16.2p3 :
- Uma atribuição composta do formulário
E1 op = E2é equivalente à expressão de atribuição simples, E1 = E1 op (E2)exceto que o valor l E1é avaliado apenas uma vez e, em relação a uma chamada de função sequenciada indeterminada, a operação de uma atribuição composta é uma única avaliação. Se E1tiver um tipo atômico, a atribuição composta é uma operação de leitura-modificação-gravação com memory_order_seq_cstsemântica de ordem de memória. 113)
Então, a questão é o que acontece c = c + 1. Aqui os operandos para +submeter conversões aritméticas usuais, e ce 1, portanto, são promovidos a int, a menos que uma arquitetura realmente maluco requer que charé promovido a unsigned int. O cálculo de +é então avaliado e o resultado do tipo int/ unsigned inté convertido novamente chare armazenado em c.
Existem três maneiras definidas pela implementação em que isso pode ser avaliado:
CHAR_MINé 0 e, portanto, charnão está assinado.
Ou charentão é promovido para intou unsigned inte se é promovido para um int, então CHAR_MAX + 1necessariamente se encaixará em um inttambém e não transbordará, ou se unsigned intpode caber ou quebrar em torno de zero. Quando o valor resultante, que é numericamente CHAR_MAX + 1ou 0após a redução do módulo, volta para c, após a redução do módulo, ele se torna 0, ou seja,CHAR_MIN
Caso contrário, charserá assinado e, se CHAR_MAX for menor que INT_MAX, o resultado CHAR_MAX + 1será ajustado a int, e o padrão C11 / C18 6.3.1.3p3 se aplica à conversão que ocorre na atribuição :
- Caso contrário, o novo tipo é assinado e o valor não pode ser representado nele; o resultado é definido pela implementação ou um sinal definido pela implementação é gerado.
Ou, se if sizeof (int) == 1 e char for assinado, charserá promovido a um inte CHAR_MAX == INT_MAX=> CHAR_MAX + 1causará um estouro de número inteiro e o comportamento será indefinido .
Ou seja, os possíveis resultados são:
Se charé um tipo inteiro não assinado, o resultado é sempre 0, ou seja CHAR_MIN.
Caso contrário, charé um tipo inteiro assinado e o comportamento é definido / não definido pela implementação:
CHAR_MIN ou algum outro valor definido pela implementação,
- um sinal definido pela implementação é gerado, possivelmente finalizando o programa,
- ou o comportamento é indefinido em algumas plataformas em que
sizeof (char) == sizeof (int).
Todas as operações de incremento c = c + 1, c += 1, c++e ++ctêm os mesmos efeitos colaterais sobre a mesma plataforma. O valor avaliado da expressão c++será o valor canterior ao incremento; para os outros três, será o valor capós o incremento.