내 코드 :
#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);
}
산출:
CHAR_MIN=-128 CHAR_MAX=127 c=-128 ()
우리는로 char
설정된 변수를 증가 CHAR_MAX
시키면로 둘러싸임을 알 수 CHAR_MIN
있습니다. 이 동작이 보장됩니까? 아니면 정의되지 않은 동작 또는 구현 지정 동작입니까? C99 표준은 이것에 대해 무엇을 말합니까?
[참고 : char 또는 C에 CHAR_MAX (127)보다 큰 값을 주면 char c = 129가 -127로 변환되는 이유는 무엇입니까? 범위를 벗어난 값에 값을 증가시키지 않고 범위를 벗어난 값을 할당하는 것에 대해 이야기하기 때문에이 질문을 다루지 않습니다.]
답변
문제는 두 가지입니다. 첫째,
char c = CHAR_MAX;
c += 1;
다른 평가
char c = CHAR_MAX;
c = c + 1;
C11 / C18 6.5.16.2p3 이므로 대답은 아닙니다 .
- 양식의 복합 대입은 lvalue 가 한 번만 평가되고 결정되지 않은 순서로 함수 호출과 관련하여 복합 대입의 연산이 단일 평가
E1 op = E2
라는E1 = E1 op (E2)
점을 제외하고 단순 대입 식과 같습니다E1
.E1
원자 유형이있는 경우 복합 지정은memory_order_seq_cst
메모리 순서 시맨틱을 사용한 읽기-수정-쓰기 작업입니다 . 113)
그렇다면 의문은에서 일어난다 c = c + 1
. 여기 피연산자하는 +
일반적인 산술 변환을 받아야하고, c
및 1
그러므로로 승진 int
정말 이상한 구조가이 요구하지 않는, char
로 승격됩니다 unsigned int
. +
그런 다음 의 계산이 평가되고 int
/ 유형의 결과 unsigned int
가로 변환 char
되어에 저장됩니다 c
.
있다 3 이 다음 평가 될 수있는 구현 정의 방법 :
-
CHAR_MIN
0이므로char
서명되지 않습니다.어느
char
다음에 승진int
또는unsigned int
과가로 승격 된 경우int
, 다음CHAR_MAX + 1
반드시에 맞는int
도, 그리고 오버 플로우, 또는 것입니다 경우unsigned int
가 맞게 제로 주위에 포장 할 수있다. 모듈로 감소 후CHAR_MAX + 1
또는 수치0
로 감소 된 결과 값이 다시c
모듈로 감소 후로 돌아 오면 , 즉 0이됩니다.CHAR_MIN
-
그렇지 않으면
char
부호가 있고CHAR_MAX
보다 작 으면INT_MAX
결과CHAR_MAX + 1
가에 적합int
하고 표준 C11 / C18 6.3.1.3p3 이 할당 시 발생하는 변환에 적용됩니다 .- 그렇지 않으면 새 유형이 서명되고 값을 표시 할 수 없습니다. 결과는 구현 정의되거나 구현 정의 신호가 발생합니다.
-
또는 iff
sizeof (int) == 1
및char
signed, 그런 다음char
으로 승격int
되고CHAR_MAX == INT_MAX
=>CHAR_MAX + 1
는 정수 오버플로를 발생시키고 동작은 정의되지 않습니다 .
즉 가능한 결과는 다음과 같습니다.
-
경우
char
부호없는 정수 타입이며, 결과는 항상0
예CHAR_MIN
. -
그렇지 않으면
char
부호있는 정수 유형이며 동작은 구현 정의 / 정의되지 않습니다.CHAR_MIN
또는 다른 구현 정의 값- 구현 정의 신호가 발생하여 프로그램을 종료 할 수 있습니다.
- 또는 일부 플랫폼에서 동작이 정의되어 있지 않습니다
sizeof (char) == sizeof (int)
.
모든 증분 작업은 c = c + 1
, c += 1
, c++
와 ++c
같은 플랫폼에서 동일한 부작용을 가지고있다. 표현식의 평가 된 값은 증분 이전의 c++
값입니다 c
. 다른 세 개 c
는 증분 후 값이 됩니다.