부호있는 정수 오버플로가 C ++에서 여전히 정의되지 않은 동작입니까?


82

아시다시피 부호있는 정수 오버플로는 정의되지 않은 동작 입니다. 그러나 C ++ 11 cstdint문서 에는 흥미로운 것이 있습니다.

패딩 비트가없고 음수 값에 대해 2의 보수를 사용 하는 정확히 8, 16, 32 및 64 비트 너비의 부호있는 정수 유형 (구현이 유형을 직접 지원하는 경우에만 제공됨)

링크보기

그리고 여기 제 질문은 : 표준가 있음을 명시 적으로 말한다 이후 int8_t, int16_t, int32_tint64_t부정적인 번호 2의 보완, 여전히 오버 플로우 이러한 유형의 정의되지 않은 행동입니까?

편집 C ++ 11 및 C11 표준을 확인했으며 여기에 내가 찾은 내용이 있습니다.

C ++ 11, §18.4.1 :

헤더는 C 표준의 7.20과 동일하게 모든 기능, 유형 및 매크로를 정의합니다.

C11, §7.20.1.1 :

typedef 이름 intN_t은 너비가 N이고 패딩 비트가없고 2의 보수 표현이있는 부호있는 정수 유형을 지정합니다. 따라서 int8_t는 너비가 정확히 8 비트 인 부호있는 정수 유형을 나타냅니다.


14
C ++에 대한 유일한 기본 문서가 표준 이라는 것을 잊지 마십시오 . 그 밖의 모든 것, 심지어 CppReference와 같은 위키도 보조 소스입니다. 그것이 틀렸다는 의미는 아닙니다. 전적으로 신뢰할 수 없습니다.
니콜 올가미

나는 그것이 UB가 될 것으로 기대하고 C에서 이러한 유형에 대한 면제가 없으며 C ++에서 왜 추가하는지 모르겠습니다.
Daniel Fischer


3
나는 약간 혼란스러워한다 : 문장의 동사는 "각각 정확히 8, 16, 32 및 64 비트의 너비를 가진 부호있는 정수 유형이고 패딩 비트가없고 음수 값에 대해 2의 보수를 사용합니다 (구현이 직접 지원하는 경우에만 제공됨). 유형)?" 약간 누락 되었습니까? 무슨 뜻이에요?
YSC

C ++ 11은 C11이 아닌 C99를 기반으로합니다. 그러나 어쨌든 중요하지 않습니다
LF

답변:


80

이러한 유형의 오버플로는 정의되지 않은 동작입니까?

예. C ++ 11 표준의 단락 5/4에 따라 (일반적인 표현과 관련하여) :

표현식을 평가하는 동안 결과가 수학적으로 정의되지 않았거나 해당 유형의 표현 가능한 값 범위에 있지 않으면 동작이 정의되지 않습니다 . [...]

이러한 부호있는 유형에 대해 2의 보수 표현이 사용된다는 사실은 해당 유형의 표현식을 평가할 때 산술 모듈로 2 ^ n이 사용된다는 의미는 아닙니다.

반면에 부호없는 산술과 관련 하여 표준은 다음과 같이 명시 적으로 지정합니다 (문단 3.9.1 / 4).

부호없는 정수는 선언 unsigned, 산술 모듈의 법칙에 따라야 2 ^ N 여기서, n은 정수의 특정 크기의 값 표현의 비트 수이고

이는 부호없는 산술 연산의 결과가 항상 " 수학적으로 정의 "되고 결과가 항상 표현 가능한 범위 내에 있음을 의미합니다. 따라서 5/4는 적용되지 않습니다. 각주 46은이를 설명합니다.

46) 이것은 결과적인 부호없는 정수 유형으로 표현할 수없는 결과가 결과 부호없는 정수 유형으로 나타낼 수있는 가장 큰 값보다 하나 더 큰 수의 모듈로 축소되기 때문에 부호없는 산술이 오버플로되지 않음을 의미합니다 .


1
이 단락은 또한 unsigned 오버플로가 정의되지 않았 음을 의미합니다.
Archie

8
@Archie : 부호없는 값은 부호없는 범위 모듈로 정의되기 때문에 실제로는 아닙니다 .
궤도의 가벼운 경주

3
@Archie : 나는 명확히하려고했으나 기본적으로는 LightnessRacesinOrbit에서 대답있어
앤디 배회을

1
unsigned overflow가 정의되었는지 여부는 모듈로 계산으로 인해 발생할 수없는 경우 실제로 중요하지 않습니다.
Aconcagua

1
결과가 "수학적으로 정의"되지 않은 부호없는 연산 (특히 0으로 나누기)이 있으므로 해당 문장에서 의미하는 표현이 아닐 수 있습니다. 것을 ITYM 결과가 수학적으로 정의 될 때 , 그것은 또한 C ++에서 정의합니다.
Toby Speight 2019 년

22

유형이 2의 보수 표현을 사용하도록 정의 되었기 때문에 해당 유형의 산술 오버플로가 정의되는 것을 따르지 않습니다.

부호있는 산술 오버플로의 정의되지 않은 동작은 최적화를 활성화하는 데 사용됩니다. 예를 들어 컴파일러는 a > b다음 과 같은 경우 a + 1 > b에도 가정 할 수 있습니다. 이 두 번째 검사 때문에 가능성을 수행 할 필요가 부호없는 산술에 보유하지 않습니다 a + 1에 랩 어라운드 수 있습니다 0. 또한 일부 플랫폼은 산술 오버플로에 대한 트랩 신호를 생성 할 수 있습니다 (예 : http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html 참조 ). 표준은이를 계속해서 허용합니다.


5
많은 사람들이 트랩의 가능성에 대해 더 많이 "걱정"한다는 점은 주목할 가치가 있지만 컴파일러 가정은 실제로 더 교활합니다 (구현 정의 동작과 달리 구현 정의 동작과 정의되지 않은 동작 사이에 범주가 있었으면하는 이유 중 하나) 일관된 문서화 된 방식으로 작업을 수행하려면 특정 구현이 필요합니다. "구현 제한"동작을 원합니다.이 동작은 어떤 결과로 발생할 수있는 모든 일을 지정해야하는 구현이 필요합니다 (사양에는 정의되지 않은 동작이 명시 적으로 포함될 수 있지만 .. .
supercat 2015

3
... 실용적 일 때 구현이 더 구체적이되도록 권장됩니다). 2의 보수 숫자가 자연스럽게 "래핑"되는 하드웨어에서는 래핑 된 정수 결과가 하나 또는 두 개의 명령어로 하드웨어가 수행 할 수있는 계산을 정수 오버플로없이 수행하려는 많은 명령어를 실행하려는 코드에 대해 합리적인 이유가 없습니다. .
supercat

1
@supercat 사실, 래핑 된 결과를 원하는 코드는 (2의 보완 CPU에서) 피연산자를 해당하는 부호없는 유형으로 캐스팅하고 연산을 수행 할 수 있습니다 (그런 다음 다시 캐스팅하여 구현 정의 값을 얻음). 이것은 더하기, 빼기 및 곱하기를 위해 작동합니다. . 유일한 문제는 나누기, 모듈로 및 abs. 작동하는 작업의 경우 서명 된 arthmetic보다 더 많은 지침이 필요하지 않습니다.
Ruslan

@Ruslan : 코드에 정확하게 래핑 된 결과가 필요한 경우 unsigned 로의 캐스트는 추악하지만 반드시 추가 코드를 생성하지는 않습니다. 더 큰 문제는 "잠재적으로 흥미로운"후보를 신속하게 식별해야하는 코드로, 대부분의 시간을 흥미롭지 않은 후보를 거부하는 데 소비하게됩니다. 컴파일러에게 부호있는 정수 값으로 추가 정밀도를 임의로 유지하거나 버릴 수있는 자유를 제공하지만 정수 유형으로의 캐스트가 이러한 정밀도를 잘라야하는 경우 오버플로 UB를 만들면 얻을 수있는 대부분의 유용한 최적화를 사용할 수 있습니다. ...
supercat

...하지만 정확한 래핑이 필요한 코드가 두 개가 아닌 하나의 캐스트를 사용하도록 허용하고 (예 : (int)(x+y)>z래핑 된 결과를 비교) 프로그래머가 x+y>z코드가 경우에 0 또는 1을 산출하는 것이 허용되는 경우 에 작성할 수 있습니다. 다른 부작용이없는 경우 오버플 로가 발생 합니다. 0 또는 1이 동등하게 허용되는 결과라면 프로그래머가 둘 중 하나가 아닌이를 작성하도록 (long)x+y>z하거나 (int)((unsigned)x+y)>z컴파일러가 후자의 함수 중 주어진 컨텍스트에서 더 저렴한 것을 선택할 수 있도록 허용합니다 [각각의 경우에는 더 저렴합니다].
supercat

1

그렇게 확신합니다.

표준 문서에서 (4 및 5 페이지) :

1.3.24 정의되지 않은 동작

이 국제 표준이 요구 사항을 부과하지 않는 행동

[참고 :이 국제 표준이 행동에 대한 명시적인 정의를 생략하거나 프로그램이 잘못된 구성 또는 잘못된 데이터를 사용하는 경우 정의되지 않은 동작이 예상 될 수 있습니다. 허용되지 않는 정의되지 않은 동작은 예측할 수없는 결과로 상황을 완전히 무시하는 것, 번역 또는 프로그램 실행 중에 환경 특성 (진단 메시지 발행 여부에 관계없이)의 문서화 된 방식으로 동작하는 것, 번역 또는 실행 종료 (발행 포함)에 이르기까지 다양합니다. 진단 메시지). 많은 잘못된 프로그램 구성은 정의되지 않은 동작을 발생시키지 않습니다. 진단을 받아야합니다 .-- end note]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.