Mój kod:
#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);
}
Wynik:
CHAR_MIN=-128 CHAR_MAX=127 c=-128 ()
Widzimy, że kiedy zwiększamy char
zestaw zmiennych do CHAR_MAX
, zawija się ono do CHAR_MIN
. Czy to zachowanie jest gwarantowane? A może będzie to zachowanie niezdefiniowane lub określone w implementacji? Co na ten temat mówi standard C99?
[Uwaga: Co się stanie, jeśli wartość char niż CAR_MAX (127) będzie większa od C lub C - dlaczego char c = 129 zamieni się na -127? nie rozwiązuje tego pytania, ponieważ mówią o przypisywaniu wartości spoza zakresu, a nie zwiększaniu wartości do wartości spoza zakresu.]
c
char
language-lawyer
standards
integer-overflow
Samotny uczeń
źródło
źródło
Odpowiedzi:
Pytanie jest dwojakie: po pierwsze, jest
ocenione inaczej niż
a odpowiedź brzmi nie, nie jest , ponieważ C11 / C18 6.5.16.2p3 :
Następnie pojawia się pytanie, co się dzieje
c = c + 1
. Oto argumenty do+
poddane zwyczajowym arytmetycznych konwersje, ac
i1
dlatego są promowane naint
, chyba że naprawdę głupi architektura wymaga,char
jest promowany dounsigned int
. Następnie obliczane+
jest obliczenie , a wynik typuint
/unsigned int
jest konwertowany z powrotemchar
i zapisywany wc
.Istnieją 3 zdefiniowane sposoby wdrożenia, w których można to następnie ocenić:
CHAR_MIN
ma wartość 0 i dlategochar
jest niepodpisany.Albo
char
jest następnie podwyższony doint
lubunsigned int
jeśli jest promowany do stopniaint
, wówczasCHAR_MAX + 1
koniecznie wpasować sięint
też i nie przelewowy, lubunsigned int
może pasować lub owinąć wokół zera. Jeżeli otrzymana wartość, która jest liczbowo alboCHAR_MAX + 1
czy0
po redukcji modulo, z powrotem doc
po redukcji modulo stanie się 0, czyliCHAR_MIN
W przeciwnym razie
char
jest podpisany, a jeśliCHAR_MAX
jest mniejszy niżINT_MAX
, wynikCHAR_MAX + 1
będzie pasowałint
, a do konwersji, która ma miejsce po przypisaniu, stosuje się standard C11 / C18 6.3.1.3p3 :Lub, iff
sizeof (int) == 1
ichar
jest podpisany, a następniechar
awansowany naint
, aCHAR_MAX == INT_MAX
=>CHAR_MAX + 1
spowoduje przepełnienie liczb całkowitych, a zachowanie będzie niezdefiniowane .To znaczy możliwe wyniki to:
Jeśli
char
jest liczbą całkowitą bez znaku, wynikiem jest zawsze0
, tjCHAR_MIN
.W przeciwnym razie
char
jest typem całkowitym ze znakiem, a zachowanie jest zdefiniowane / niezdefiniowane w implementacji:CHAR_MIN
lub jakąś inną wartość zdefiniowaną w implementacji,sizeof (char) == sizeof (int)
.Wszystkie operacje inkrementacji
c = c + 1
,c += 1
,c++
i++c
mają takie same skutki uboczne na tej samej platformie. Obliczona wartość wyrażeniac++
będzie wartościąc
przed przyrostem; dla pozostałych trzech będzie to wartośćc
po zwiększeniu.źródło
sizeof(int) == 1
wymagałobyCHAR_BITS >= 16
, prawda?<pedantic>
IDK o,CHAR_BITS
aleCHAR_BIT
chciałbym>= 16</pedantic>
.char
zawsze powinien być domyślnie niepodpisany.