C: 표준 및 컴파일러의 정수 오버플로
Carl Norum 덕분에 적절한 표준 참조를 포함하도록 편집되었습니다.
C 표준 상태
식을 평가하는 동안 예외적인 조건이 발생하는 경우(즉, 결과가 수학적으로 정의되지 않았거나 해당 유형에 대해 표현 가능한 값의 범위에 있지 않은 경우), 동작은 정의되지 않습니다.
정수 오버플로우에서 특정 동작을 보장하는 컴파일러 스위치가 있습니까?코마귀를 피하고 싶습니다.특히, 저는 컴파일러가 오버플로를 하도록 강요하고 싶습니다.
고유성을 위해 표준은 C99, 컴파일러는 gcc로 합시다.하지만 다른 컴파일러(icc, cl)와 다른 표준(C1x, C89)에 대한 답변에 관심이 있습니다.사실 C/C++ 관중들을 짜증나게 하기 위해서라도 C++0x, C++03, C++98에 대한 답변을 주시면 감사하겠습니다.
참고: 국제 표준 ISO/IEC 10967-1이 여기에 관련될 수 있지만, 제가 알 수 있는 한 이는 정보를 제공하는 부속서에서만 언급되었습니다.
를 보고 다음을(를)
-ftrapv
이 옵션은 덧셈, 뺄셈, 곱셈 작업에서 서명된 오버플로에 대한 트랩을 생성합니다.
-frapv
이 옵션은 컴파일러에게 덧셈, 뺄셈, 곱셈의 부호화된 산술 오버플로가 2보 표현을 사용하여 랩어라운드한다고 가정하도록 지시합니다.이 플래그는 일부 최적화를 활성화하고 다른 최적화는 비활성화합니다.이 옵션은 Java 언어 사양에 따라 Java 프론트엔드에 대해 기본적으로 활성화됩니다.
C99 답변의 경우, 6.5 표현식, 5항이 여러분이 찾고 있는 내용이라고 생각합니다.
식을 평가하는 동안 예외적인 조건이 발생하는 경우(즉, 결과가 수학적으로 정의되지 않았거나 해당 유형에 대해 표현 가능한 값의 범위에 있지 않은 경우), 동작은 정의되지 않습니다.
그것은 만약 당신이 넘치게 된다면, 당신은 운이 없다는 것을 의미합니다 - 어떤 종류의 행동도 보장되지 않습니다.서명되지 않은 유형은 특수한 경우이며, 오버플로우가 발생하지 않습니다(6.2.5 유형, 9항):
서명되지 않은 피연산자를 포함하는 계산은 결코 오버플로우될 수 없습니다. 결과 서명되지 않은 정수 유형으로 표현할 수 없는 결과는 결과 유형으로 표현할 수 있는 가장 큰 값보다 1 큰 모듈로 감소되기 때문입니다.
C++는 같은 문장을 가지고 있으며, 약간 다르게 표현됩니다.
5 문단 4의 표현:
식을 평가하는 동안 결과가 수학적으로 정의되지 않거나 해당 유형에 대해 표현 가능한 값의 범위에 포함되지 않으면 동작이 정의되지 않습니다.[참고: 기존 C++ 구현의 대부분은 정수 오버플로를 무시합니다.0으로 나눗셈을 처리하고, 0 나눗셈을 사용하여 나머지를 형성하며, 모든 부동 소수점 예외는 기계마다 다르며, 대개 라이브러리 함수에 의해 조정할 수 있습니다.—엔드노트]
3.9.1 기본 형식, 문단 4:
없는 된 ,
unsigned
, 산술 모듈로 2^n의 법칙을 준수해야 합니다. 여기서 n은 정수의 특정 크기의 값 표현에 있는 비트 수입니다.
C99에서 일반적인 거동은 6.5/5에 설명되어 있습니다.
식을 평가하는 동안 예외적인 조건이 발생하는 경우(즉, 결과가 수학적으로 정의되지 않았거나 해당 유형에 대해 표현 가능한 값의 범위에 있지 않은 경우), 동작은 정의되지 않습니다.
서명되지 않은 유형의 동작은 6.2.5/9에 설명되어 있습니다. 이는 기본적으로 서명되지 않은 유형의 작업이 예외적인 조건으로 이어지지 않음을 나타냅니다.
서명되지 않은 피연산자를 포함하는 계산은 결코 오버플로우될 수 없습니다. 결과 서명되지 않은 정수 유형으로 표현할 수 없는 결과는 결과 유형으로 표현할 수 있는 가장 큰 값보다 1 큰 모듈로 감소되기 때문입니다.
한 옵션인 가 .-ftrapv
된 정수 오버플로를 입니다.입니다.
완성도를 위해, 저는 Clang이 이제 언어 확장자로서 "산술 내장을 확인했다"고 덧붙이고 싶습니다.다음은 확인된 부호 없는 곱셈을 사용하는 예입니다.
unsigned x, y, result;
...
if (__builtin_umul_overflow(x, y, &result)) {
/* overflow occured */
...
}
...
http://clang.llvm.org/docs/LanguageExtensions.html#checked-arithmetic-builtins
6.2.5 문단 9는 다음과 같습니다.
부호화된 정수 유형의 음이 아닌 값의 범위는 해당 부호화되지 않은 정수 유형의 하위 범위이며, 각 유형에서 동일한 값의 표현은 동일합니다.31) 부호 없는 피연산자를 포함하는 계산은 결코 오버플로우될 수 없습니다. 결과 부호 없는 정수형으로 표현할 수 없는 결과는 결과형으로 표현할 수 있는 가장 큰 값보다 1 큰 모듈로 감소되기 때문입니다.
이전 게시물들은 모두 C99 표준에 대해 언급했지만, 사실 이 보증은 이미 더 일찍 가능했습니다.
제6.1.2.5절 제5항 유형
C89 표준 주들의
서명되지 않은 피연산자를 포함하는 계산은 결코 오버플로우될 수 없습니다. 결과 서명되지 않은 정수 유형으로 표현할 수 없는 결과는 결과 서명되지 않은 정수 유형으로 표현할 수 있는 가장 큰 값보다 1 큰 모듈로 감소되기 때문입니다.
이것은 C 프로그래머가 모든 부호 없는 분할을 어떤 상수로 대체하여 C의 모듈로 2^N 구간 연산에 의해 형성된 링의 역요소와 곱셈으로 대체할 수 있음에 유의합니다.
그리고 이것은 역수 값을 갖는 고정 소수점 곱셈으로 나눗셈을 근사화함으로써 필요한 것이기 때문에 "수정" 없이 수행할 수 있습니다.
대신 확장 유클리디언 알고리즘을 사용하여 역원소를 찾고 이를 승수로 사용할 수 있습니다. (물론 휴대성을 유지하기 위해서는 결과가 동일한 비트폭을 갖도록 하기 위해 비트 와이즈 AND 연산도 적용되어야 합니다.)
대부분의 C 컴파일러는 이미 이를 최적화로 구현하고 있다는 점을 언급할 필요가 있을 것입니다.그러나 이러한 최적화는 보장되지 않으며, 따라서 속도가 중요한 상황에서 프로그래머가 수동으로 이러한 최적화를 수행하는 것은 여전히 흥미로울 수 있지만, C 최적화기의 기능은 알려지지 않았거나 특히 취약합니다.
그리고 마지막으로, 그렇게 하려고 하는 이유는 다음과 같습니다.곱셈을 위한 기계 수준의 명령은 일반적으로 분할 명령보다 훨씬 빠르며, 특히 고성능 CPU의 경우 더욱 그렇습니다.
C/C++에서 오버플로에 대해 균일한 동작을 수행하기 위해 사용할 수 있는 컴파일러 스위치가 있는지 잘 모르겠습니다.다른 옵션은 다음을 사용하는 것입니다.SafeInt<T>
템플릿을 사용합니다.크로스 플랫폼 C++ 템플릿으로 모든 유형의 정수 연산에 대한 최종 오버플로우/언더플로우 검사를 제공합니다.
언급URL : https://stackoverflow.com/questions/3679047/integer-overflow-in-c-standards-and-compilers
'programing' 카테고리의 다른 글
양식 제출 jQuery가 작동하지 않습니다. (0) | 2023.10.04 |
---|---|
새로 고침과 같은 표준 Android 메뉴 아이콘 (0) | 2023.10.04 |
MySQL의 INT와 UUID의 차이 (0) | 2023.10.04 |
요소가 디바인지 확인합니다. (0) | 2023.10.04 |
동적으로 생성된 Wordpress Wysiwyg Editor(wp_editor)가 제대로 표시되지 않음 (0) | 2023.10.04 |