Mon code:
#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);
}
Production:
CHAR_MIN=-128 CHAR_MAX=127 c=-128 ()
Nous voyons que lorsque nous incrémentons un char
ensemble de variables à CHAR_MAX
, il s'enroule autour de CHAR_MIN
. Ce comportement est-il garanti? Ou est-ce que ce sera un comportement non défini ou un comportement spécifié par l'implémentation? Que dit la norme C99 à ce sujet?
[Remarque: que se passe-t-il lorsque vous donnez une valeur supérieure à CHAR_MAX (127) à char ou C- pourquoi char c = 129 se convertira en -127? ne répond pas à cette question car ils parlent d'assigner une valeur hors plage et non d'incrémenter une valeur à une valeur hors plage.]
c
char
language-lawyer
standards
integer-overflow
Apprenant solitaire
la source
la source
Réponses:
La question est double: premièrement,
évalué différemment de
et la réponse est non, ce n'est pas le cas , car C11 / C18 6.5.16.2p3 :
Ensuite, la question est de savoir ce qui se passe
c = c + 1
. Voici les opérandes à+
subir des conversions arithmétiques habituelles, etc
et1
sont donc promusint
, à moins d' une architecture vraiment farfelue exige quechar
est promuunsigned int
. Le calcul de+
est ensuite évalué et le résultat de typeint
/unsigned int
est reconvertichar
et stocké dansc
.Il existe 3 façons définies par l'implémentation qui peuvent ensuite être évaluées:
CHAR_MIN
est 0 etchar
n'est donc pas signé.L'un
char
ou l' autre est alors promu versint
ouunsigned int
et s'il est promu vers unint
, ilCHAR_MAX + 1
rentrera nécessairement dans unint
aussi et ne débordera pas, ou s'ilunsigned int
peut s'ajuster ou se terminer à zéro. Lorsque la valeur résultante, qui est numériquement soitCHAR_MAX + 1
ou0
après réduction modulo, de retour àc
, après réduction modulo , il deviendra 0, à savoirCHAR_MIN
Sinon
char
est signé, alors siCHAR_MAX
est plus petit queINT_MAX
, le résultat deCHAR_MAX + 1
s'adaptera à unint
, et la norme C11 / C18 6.3.1.3p3 s'applique à la conversion qui se produit lors de l' affectation :Ou, ssi
sizeof (int) == 1
etchar
est signé, puischar
est promu enint
, etCHAR_MAX == INT_MAX
=>CHAR_MAX + 1
provoquera un débordement d'entier et le comportement ne sera pas défini .C'est-à-dire que les résultats possibles sont:
Si
char
est un type entier non signé, le résultat est toujours0
, ieCHAR_MIN
.Sinon, il
char
s'agit d'un type d'entier signé et le comportement est défini par l'implémentation / non défini:CHAR_MIN
ou une autre valeur définie par l'implémentation,sizeof (char) == sizeof (int)
.Toutes les opérations d'incrémentation
c = c + 1
,c += 1
,c++
et++c
ont les mêmes effets secondaires sur la même plate - forme. La valeur évaluée de l'expressionc++
sera la valeurc
avant l'incrément; pour les trois autres, ce sera la valeurc
après l'incrément.la source
sizeof(int) == 1
exigeraitCHAR_BITS >= 16
, non?<pedantic>
IDK surCHAR_BITS
mais leCHAR_BIT
ferait>= 16</pedantic>
.char
devrait toujours être non signé par défaut.