Programming

부호없는 정수 오버플로가 동작을 정의하지만 부호있는 정수 오버플로는 왜 그렇지 않습니까?

procodes 2020. 5. 10. 11:43
반응형

부호없는 정수 오버플로가 동작을 정의하지만 부호있는 정수 오버플로는 왜 그렇지 않습니까?


부호없는 정수 오버플로는 C 및 C ++ 표준에 의해 잘 정의됩니다. 예를 들어 C99 표준 ( §6.2.5/9) 상태

결과 부호없는 정수 유형으로 표현할 수없는 결과는 결과 유형으로 표현할 수있는 가장 큰 값보다 1이 큰 수의 모듈로 감소되기 때문에 부호없는 피연산자가 포함 된 계산은 절대로 흐르지 않습니다.

그러나 두 표준 모두 부호있는 정수 오버플로는 정의되지 않은 동작이라고 명시하고 있습니다. 다시 C99 표준 ( §3.4.3/1)에서

정의되지 않은 동작의 예는 정수 오버 플로우에서의 동작입니다.

이 불일치에 대한 역사적 또는 더 나은 기술적 이유가 있습니까?


역사적 이유는 대부분의 C 구현 (컴파일러)이 사용 된 정수 표현으로 구현하기 가장 쉬운 오버 플로우 동작을 사용했기 때문입니다. C 구현은 일반적으로 CPU에서 사용하는 것과 동일한 표현을 사용하므로 오버플로 동작은 CPU에서 사용하는 정수 표현을 따릅니다.

실제로는 구현에 따라 다를 수있는 부호있는 값의 표현 일뿐입니다. 하나의 보수, 2의 보수, 부호 크기. 부호없는 유형의 경우 표준이 이진 표현이 하나만 있기 때문에 표준이 변형을 허용 할 이유가 없습니다 (표준은 이진 표현 만 허용 함).

관련 인용문 :

C99 6.2.6.1:3 :

부호없는 비트 필드와 부호없는 char 유형의 객체에 저장된 값은 순수한 이진 표기법을 사용하여 표현해야합니다.

C99 6.2.6.2:2 :

부호 비트가 1이면 값은 다음 방법 중 하나로 수정됩니다.

-부호 비트가 0 인 대응 값이 무효화 됨 ( 부호 및 크기 );

-부호 비트는-(2 N ) 의 값을 갖는다 ( 2의 보수 ).

— 부호 비트의 값은 − (2 N -1)입니다 ( 1의 보수 ).


오늘날 모든 프로세서는 2의 보수 표현을 사용하지만 부호있는 산술 오버플로는 정의되지 않은 상태로 유지되며 컴파일러 제조업체는이 정의되지 않은 내용을 사용하여 최적화에 도움이되므로 정의되지 않은 상태로 유지하려고합니다. 예를 들어 이안 랜스 테일러 (Ian Lance Taylor)의 블로그 게시물 또는 Agner Fog의 불만 사항 및 버그 보고서에 대한 답변을 참조하십시오.


파스칼의 좋은 대답 (주된 동기라고 확신합니다) 외에도 일부 프로세서는 부호있는 정수 오버플로에 예외를 일으킬 수 있습니다. 물론 컴파일러가 "다른 행동을 취해야"하면 문제가 발생할 수 있습니다 ( 예를 들어 여분의 명령을 사용하여 잠재적 오버플로를 확인하고이 경우 다르게 계산합니다.

"정의되지 않은 행동"이 "작동하지 않는다"는 의미는 아닙니다. 그것은 구현이 그 상황에서 좋아하는 것을 할 수 있음을 의미합니다. 여기에는 "올바른 일"과 "경찰 부름"또는 "충돌"이 포함됩니다. 가능하면 대부분의 컴파일러는 정의하기가 비교적 쉽다고 가정 할 때 "올바른 일을"선택합니다 (이 경우에는 그렇습니다). 그러나 계산에 오버플로가 발생하면 실제로 결과가 무엇인지 이해하고 컴파일러가 예상 한 것 이외의 작업을 수행 할 수 있습니다 (컴파일러 버전, 최적화 설정 등에 따라 다를 수 있음) .


우선, C11 3.4.3은 모든 예제 및 각주와 마찬가지로 규범적인 텍스트가 아니므로 인용과 관련이 없습니다!

정수와 부동의 오버플로가 정의되지 않은 동작이라는 내용의 관련 텍스트는 다음과 같습니다.

C11 6.5 / 5

표현식을 평가하는 동안 예외 조건이 발생하는 경우 (즉, 결과가 수학적으로 정의되지 않았거나 해당 유형의 표현 가능한 값 범위에없는 경우) 동작은 정의되지 않습니다.

부호없는 정수 유형의 동작에 대한 설명은 구체적으로 여기에서 찾을 수 있습니다.

C11 6.2.5 / 9

부호있는 정수 유형의 음이 아닌 값의 범위는 해당 부호없는 정수 유형의 하위 범위이며 각 유형에서 동일한 값의 표현은 동일합니다. 부호없는 피연산자가 포함 된 계산은 결과 부호없는 정수 유형으로 표현할 수없는 결과가 결과 유형으로 표현할 수있는 가장 큰 값보다 1이 큰 모듈로 감소되므로 오버 플로우 할 수 없습니다.

이것은 부호없는 정수 타입을 특별한 경우로 만듭니다.

또한 모든 유형이 부호 있는 유형으로 변환 되어 이전 값을 더 이상 표시 할 수없는 경우 예외가 있습니다. 신호가 발생하더라도 동작은 구현에 따라 정의됩니다.

C11 6.3.1.3

6.3.1.3 부호있는 정수와 부호없는 정수

정수 유형의 값이 _Bool 이외의 다른 정수 유형으로 변환 될 때 새 유형으로 값을 표시 할 수 있으면 변경되지 않습니다.

그렇지 않으면 새 유형에 부호가없는 경우 값이 새 유형의 범위에 올 때까지 새 유형에 표시 될 수있는 최대 값보다 하나 이상을 반복적으로 더하거나 빼서 값이 변환됩니다.

그렇지 않으면 새 유형이 서명되고 값을 표시 할 수 없습니다. 결과는 구현 정의되거나 구현 정의 신호가 발생합니다.


다른 문제뿐만 아니라 부호 수학 랩 추상 대수 그룹으로 (값의 쌍에 대해, 무엇보다도 그 의미의 행동 부호없는 정수 타입하게 가지고 언급 XY다른 값이 존재하는 것, Z그런 것을 X+Z의지가 제대로 캐스트 경우를 , 평등 Y, Y-Z의지X). 부호없는 값이 단순히 저장 위치 유형이고 중간 표현식 유형이 아닌 경우 (예 : 가장 큰 정수 유형과 부호없는 동등 항목이없고 부호없는 유형에 대한 산술 연산이 처음 큰 부호있는 유형으로 변환 된 것처럼 동작하는 경우) 정의 된 래핑 동작에는 그다지 필요하지 않지만 추가 역수가없는 유형으로 계산하기는 어렵습니다.

이 기능은 랩 어라운드 동작이 실제로 유용한 상황 (예 : TCP 시퀀스 번호 또는 해시 계산과 같은 특정 알고리즘)에 도움이됩니다. 또한 계산을 수행하고 오버플로 여부를 확인하는 것이 오버플로 여부를 미리 확인하는 것보다, 특히 계산에 사용 가능한 가장 큰 정수 유형이 포함 된 경우 오버플로를 감지해야하는 상황에서 도움이 될 수 있습니다.


부호없는 산술이 정의되는 또 다른 이유는 부호없는 숫자가 정수 모듈로 2 ^ n을 형성하기 때문입니다. 여기서 n은 부호없는 숫자의 너비입니다. 부호없는 숫자는 단순히 십진수 대신 이진수를 사용하여 표현 된 정수입니다. 모듈러스 시스템에서 표준 작업을 수행하는 것은 잘 알려져 있습니다.

The OP's quote refers to this fact, but also highlights the fact that there is only one, unambiguous, logical way to represent unsigned integers in binary. By contrast, Signed numbers are most often represented using two's complement but other choices are possible as described in the standard (section 6.2.6.2).

Two's complement representation allows certain operations to make more sense in binary format. E.g., incrementing negative numbers is the same that for positive numbers (expect under overflow conditions). Some operations at the machine level can be the same for signed and unsigned numbers. However, when interpreting the result of those operations, some cases don't make sense - positive and negative overflow. Furthermore, the overflow results differ depending on the underlying signed representation.

참고URL : https://stackoverflow.com/questions/18195715/why-is-unsigned-integer-overflow-defined-behavior-but-signed-integer-overflow-is

반응형