char 값이 CHAR_MAX로 설정되어 CHAR_MIN으로 줄 바꿈이 보장됩니까?


10

내 코드 :

#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로 변환되는 이유는 무엇입니까? 범위를 벗어난 값에 값을 증가시키지 않고 범위를 벗어난 값을 할당하는 것에 대해 이야기하기 때문에이 질문을 다루지 않습니다.]


증분은 할당입니다.
윌리엄 퍼셀

2
문자가 서명되었는지 여부에 따라 다릅니다. 부호있는 정수의 오버 플로우는 정의되지 않은 동작입니다. 따라서 출력은 무엇이든 될 수 있습니다.
DaBler

답변:


15

문제는 두 가지입니다. 첫째,

char c = CHAR_MAX;
c += 1;

다른 평가

char c = CHAR_MAX;
c = c + 1;

C11 / C18 6.5.16.2p3 이므로 대답은 아닙니다 .

  1. 양식의 복합 대입은 lvalue 가 한 번만 평가되고 결정되지 않은 순서로 함수 호출과 관련하여 복합 대입의 연산이 단일 평가 E1 op = E2라는 E1 = E1 op (E2)점을 제외하고 단순 대입 식과 같습니다 E1. E1원자 유형이있는 경우 복합 지정은 memory_order_seq_cst메모리 순서 시맨틱을 사용한 읽기-수정-쓰기 작업입니다 . 113)

그렇다면 의문은에서 일어난다 c = c + 1. 여기 피연산자하는 +일반적인 산술 변환을 받아야하고, c1그러므로로 승진 int정말 이상한 구조가이 요구하지 않는, char로 승격됩니다 unsigned int. +그런 다음 의 계산이 평가되고 int/ 유형의 결과 unsigned int가로 변환 char되어에 저장됩니다 c.

있다 3 이 다음 평가 될 수있는 구현 정의 방법 :

  • CHAR_MIN0이므로 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할당 시 발생하는 변환에 적용됩니다 .

    1. 그렇지 않으면 새 유형이 서명되고 값을 표시 할 수 없습니다. 결과는 구현 정의되거나 구현 정의 신호가 발생합니다.
  • 또는 iff sizeof (int) == 1 char signed, 그런 다음 char으로 승격 int되고 CHAR_MAX == INT_MAX=> CHAR_MAX + 1는 정수 오버플로를 발생시키고 동작은 정의되지 않습니다 .

즉 가능한 결과는 다음과 같습니다.

  • 경우 char부호없는 정수 타입이며, 결과는 항상 0CHAR_MIN.

  • 그렇지 않으면 char부호있는 정수 유형이며 동작은 구현 정의 / 정의되지 않습니다.

    • CHAR_MIN 또는 다른 구현 정의 값
    • 구현 정의 신호가 발생하여 프로그램을 종료 할 수 있습니다.
    • 또는 일부 플랫폼에서 동작이 정의되어 있지 않습니다 sizeof (char) == sizeof (int).

모든 증분 작업은 c = c + 1, c += 1, c++++c같은 플랫폼에서 동일한 부작용을 가지고있다. 표현식의 평가 된 값은 증분 이전의 c++값입니다 c. 다른 세 개 c는 증분 후 값이 됩니다.


1
sizeof(int) == 1필요 CHAR_BITS >= 16합니까?
sepp2k

3
@ sepp2k는 <pedantic>대한 IDK CHAR_BITS하지만 CHAR_BIT>= 16</pedantic>.
Antti Haapala

2
char기본적으로 항상 서명을 해제해야하는 또 다른 이유 입니다.
chqrlie

1
@chqrlie 나는 유감스럽게도 서명되지 않은 것이 역사상 나중에 있기 때문에 기본적으로 서명 된 것일 수 있으며 EOF에 적합 할 것으로 예상되는 깨진 프로그램의 양 때문에 일부 cr * ppy 시스템에서 변경하기가 너무 어려울 수 있음에 동의합니다. char ..
Antti Haapala

1
때로는 직접 응답을 추가하는 것이 분명합니다. "char 값이 CHAR_MAX로 설정되어 CHAR_MIN으로 줄 바꿈이 보장됩니까?" -> 아니오
chux-
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.