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 E1
tiver um tipo atômico, a atribuição composta é uma operação de leitura-modificação-gravação com memory_order_seq_cst
semâ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 c
e 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 char
e armazenado em c
.
Existem três maneiras definidas pela implementação em que isso pode ser avaliado:
CHAR_MIN
é 0 e, portanto, char
não está assinado.
Ou char
então é promovido para int
ou unsigned int
e se é promovido para um int
, então CHAR_MAX + 1
necessariamente se encaixará em um int
também e não transbordará, ou se unsigned int
pode caber ou quebrar em torno de zero. Quando o valor resultante, que é numericamente CHAR_MAX + 1
ou 0
apó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, char
será assinado e, se CHAR_MAX
for menor que INT_MAX
, o resultado CHAR_MAX + 1
será 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, char
será promovido a um int
e CHAR_MAX == INT_MAX
=> CHAR_MAX + 1
causará 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 ++c
têm os mesmos efeitos colaterais sobre a mesma plataforma. O valor avaliado da expressão c++
será o valor c
anterior ao incremento; para os outros três, será o valor c
após o incremento.