programing

0으로 구분: C 및/또는 C++에 정의되지 않은 행동 또는 구현?

goodsources 2023. 10. 18. 22:03
반응형

0으로 구분: C 및/또는 C++에 정의되지 않은 행동 또는 구현?

0으로 나누는 것과 관련하여, 표준은 다음과 같이 말합니다.

C99 6.5.5p5 - 연산자의 결과는 첫 번째 피연산자를 두 번째 피연산자로 나눈 몫이고, % 연산자의 결과는 나머지입니다.두 작업 모두에서 두 번째 피연산자의 값이 0이면 동작이 정의되지 않습니다.

C++035.6.4 - 이진 / 연산자는 몫을 산출하고 이진 % 연산자는 첫 번째 식을 두 번째 식으로 나눈 나머지를 산출합니다./ 또는 %의 두 번째 피연산자가 0이면 동작이 정의되지 않습니다.

위의 단락들을 액면 그대로 받아들인다면, 답은 두 언어 모두에 대한 정의되지 않은 행동입니다.그러나 C99 표준에서 더 아래를 보면 모순되는 것으로 보이는 다음 단락을 볼 수 있습니다(1).

C99 7.12p4 - 매크로 인피니티는 양 또는 부호가 없는 무한대를 나타내는 부동태의 일정한 표현으로 확장됩니다.

표준에는 정의되지 않은 행동이 (잠재적으로) 모순되는 진술로 대체될 수 없는 일종의 황금 규칙이 있습니까?그것을 제외하고는, 만약 당신의 구현이 인피니티 매크로를 정의한다면, 0으로 나누는 것이 그렇게 정의된다는 결론을 내리는 것이 무리는 아니라고 생각합니다.그러나 구현에서 이러한 매크로를 정의하지 않으면 동작이 정의되지 않은 것입니다.

이 문제에 대해 두 언어 각각의 합의점이 무엇인지 궁금합니다.만약 우리가 정수 분할에 대해 이야기한다면 답이 바뀔까요?int i = 1 / 0부동 소수점 분할 대비float i = 1.0 / 0.0?

주 (1) C++03 표준은 다음과 같은 내용을 담고 있습니다.<cmath>INFINITY 매크로가 포함된 라이브러리.

모순이 없다고 봅니다.0으로 나눈 값은 정의되지 않았습니다. 마침표....에 대해서는 일절 언급이에 관한 언급이 없습니다. INFINITY가 인용된 텍스트의 어디에나 정의되지 않는.

수학에서 1/0 = 무한대로 정의되는 곳은 없습니다.그렇게 해석할 도 있겠지만, 그것은 건전한 사실이라기보다는 개인적인, "바로가기" 스타일의 해석입니다.

1/0은 무한대가 아닙니다.

lim 1/x = ∞ (x -> +0)

이것은 수학에서 가장 순수한 문제가 아니라 C/C++ 문제였습니다.

  • 현대의 모든 C 컴파일러/FPU가 사용하는 IEEE 754 표준에 따르면, 우리는
    • 3.0 / 0.0 = INF
    • 0.0 / 0.0 = NaN
    • -3.0 / 0.0 = -INF

FPU에는 원하는 경우 예외를 생성하도록 설정할 수 있는 상태 플래그가 있지만, 이 플래그는 일반적인 것이 아닙니다.

INF가 유용한 결과일 때 INF는 분기를 피하는 데 상당히 유용할 수 있습니다.여기서 토론 보기

http://people.eecs.berkeley.edu/ ~wkahan/ieee754 status/IEEE754.PDF

왜 그럴까요?

그것은 수학적으로 말이 되지 않습니다. 일반적으로 수학에서 1/x가 ∞로 정의되는 것은 아닙니다.또한 최소한 -1/x와 0/x는 동일한 ∞이 될 수 없습니다.

일반적으로 0에 의한 나눗셈을 참조하고, 특히 컴퓨터 산술에 관한 부분을 참조합니다.

다음을 정의하는 구현__STDC_IEC_559__부속서 F에 제시된 요건을 준수할 것을 요구하며, 이는 다시 IEC 60559와 일치하는 부동 소수점 의미론을 요구합니다.이 표준은 부동 소수점을 0으로 나누는 행위에 대해 다음과 같이 정의하지 않은 구현에 대해 요구사항을 부과하지 않습니다.__STDC_IEC_559__, 정의를 내리는 사람들에겐 그렇겠죠IEC 60559가 동작을 지정하지만 C 표준이 지정하지 않는 경우 다음을 정의하는 컴파일러__STDC_IEC_559__C 표준에 의해 IEC 표준에 설명된 대로 동작하도록 요구됩니다.

IEC 60559 (또는 미국 표준 IEEE-754)에 의해 정의된 바와 같이 0을 0으로 나누는 것은 NaN을 산출하고, 부동 소수점 수를 양의 0 또는 문자 그대로 상수 0으로 나누는 것은 배당과 동일한 부호를 갖는 INF 값을 산출하고, 부동 소수점 수를 음의 0으로 나누는 것은 반대 부호를 갖는 INF를 산출합니다.

C99 드래프트만 받았습니다.§7.12/4에서는 다음과 같이 말합니다.

매크로

    INFINITY

사용 가능한 경우 양 또는 부호 없는 무한대를 나타내는 유형 플로트의 상수로 확장되고, 그렇지 않은 경우 유형의 양의 상수로 확장됩니다.float번역할 때마다 넘쳐납니다.

:INFINITY부동 소수점 오버플로 측면에서 정의될 수 있으며 반드시 0으로 나눌 필요는 없습니다.

INFINITY 매크로의 경우: IEEE754 표준에는 +/- 인피니티를 나타내는 명시적인 코딩이 있는데, 이는 모든 지수 비트가 설정되고 모든 분수 비트가 삭제된 경우(분수 비트가 설정된 경우 NaN을 나타냄)

나의 컴파일러와 함께,(int) INFINITY == -2147483648, 이렇게 평가하는 표현은int i = 1/0INFINITIY가 반환될 경우 잘못된 결과가 나올 수 있습니다.

결론적으로, C99(귀하의 인용문에 따르면)는 "구현 정의"의 맥락에서 인피니티에 대해 아무 말도 하지 않습니다.둘째, 인용한 내용은 "정의되지 않은 행동"의 일관성 없는 의미를 보여주지 않습니다.


[Wikipedia 'Undefined Behavior' 페이지 인용] "C와 C++에서도 구현 정의된 동작이 사용되는데, 언어 표준에는 동작이 명시되어 있지 않지만 구현은 동작을 선택해야 하며 선택한 규칙을 문서화하고 준수해야 합니다."

좀 더 정확하게 말하면, 표준은 표준의 특정 속성이기 때문에, 그 용어들을 사용할 때 "구현 정의된"(오직 저는)을 의미합니다.C997.12p4의 인용문에는 "구현 정의"가 언급되지 않았습니다.

[C99 std(후기 초안)부터] "정의되지 않은 행위: 휴대가 불가능하거나 잘못된 데이터의 프로그램 구성자를 사용할 때 본 국제 표준이 아무런 요구 사항을 부과하지 않는 행위"

정의되지 않은 동작에 대해 "요구사항 없음"이 부과됩니다!

[C99..] "구현정의된 행위: 각 구현이 선택이 이루어지는 방법을 문서화하는 불특정 행위"

[C99..] "불특정 행위: 이 국제 표준이 두 가지 이상의 가능성을 제공하고 어떠한 경우에도 선택된 것에 더 이상의 요구 사항을 부과하지 않는 경우, 불특정 값의 사용 또는 기타 행위"

문서화는 구현이 정의된 동작을 위한 요구사항입니다.

언급URL : https://stackoverflow.com/questions/3004095/division-by-zero-undefined-behavior-or-implementation-defined-in-c-and-or-c

반응형