Meu código:
#include <stdio.h>
#include <limits.h>
int main()
{
char c = CHAR_MAX;
c += 1;
printf("CHAR_MIN=%d CHAR_MAX=%d c=%d (%c)\n", CHAR_MIN, CHAR_MAX, c, c);
}
Resultado:
CHAR_MIN=-128 CHAR_MAX=127 c=-128 ()
Vemos que, quando incrementamos um char
conjunto de variáveis para CHAR_MAX
, ele se volta para CHAR_MIN
. Esse comportamento é garantido? Ou será um comportamento indefinido ou um comportamento especificado pela implementação? O que o padrão C99 diz sobre isso?
[Nota: O que acontece quando atribuir valor maior que CHAR_MAX (127) a char ou C- por que char c = 129 será convertido em -127? não aborda essa pergunta porque eles falam sobre atribuir um valor fora do intervalo e não incrementar um valor para um valor fora do intervalo.]
c
char
language-lawyer
standards
integer-overflow
Aluno Solitário
fonte
fonte
Respostas:
A questão é dupla: em primeiro lugar, é
avaliado diferentemente de
e a resposta é não, não é , porque C11 / C18 6.5.16.2p3 :
Então, a questão é o que acontece
c = c + 1
. Aqui os operandos para+
submeter conversões aritméticas usuais, ec
e1
, portanto, são promovidos aint
, a menos que uma arquitetura realmente maluco requer quechar
é promovido aunsigned int
. O cálculo de+
é então avaliado e o resultado do tipoint
/unsigned int
é convertido novamentechar
e armazenado emc
.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 paraint
ouunsigned int
e se é promovido para umint
, entãoCHAR_MAX + 1
necessariamente se encaixará em umint
também e não transbordará, ou seunsigned int
pode caber ou quebrar em torno de zero. Quando o valor resultante, que é numericamenteCHAR_MAX + 1
ou0
após a redução do módulo, volta parac
, após a redução do módulo, ele se torna 0, ou seja,CHAR_MIN
Caso contrário,
char
será assinado e, seCHAR_MAX
for menor queINT_MAX
, o resultadoCHAR_MAX + 1
será ajustado aint
, e o padrão C11 / C18 6.3.1.3p3 se aplica à conversão que ocorre na atribuição :Ou, se if
sizeof (int) == 1
echar
for assinado,char
será promovido a umint
eCHAR_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 é sempre0
, ou sejaCHAR_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,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ãoc++
será o valorc
anterior ao incremento; para os outros três, será o valorc
após o incremento.fonte
sizeof(int) == 1
exigiriaCHAR_BITS >= 16
, certo?<pedantic>
IDK sobre,CHAR_BITS
masCHAR_BIT
faria>= 16</pedantic>
.char
sempre deve ser assinado por padrão.