IT story

C ++에서 (-2147483648> 0)이 true를 반환합니까?

hot-time 2020. 4. 11. 10:12
반응형

C ++에서 (-2147483648> 0)이 true를 반환합니까?


-2147483648은 32 비트 정수 유형의 가장 작은 정수이지만 if(...)문장 에서 오버플로되는 것처럼 보입니다 .

if (-2147483648 > 0)
    std::cout << "true";
else
    std::cout << "false";

이것은 true내 테스트에서 인쇄 됩니다. 그러나 -2147483648을 정수로 캐스트하면 결과가 달라집니다.

if (int(-2147483648) > 0)
    std::cout << "true";
else
    std::cout << "false";

인쇄 false됩니다.

혼란 스러워요. 누구든지 이것에 대해 설명 할 수 있습니까?


02-05-2012 업데이트 :

귀하의 의견에 감사드립니다. 내 컴파일러에서 int의 크기는 4 바이트입니다. 간단한 테스트를 위해 VC를 사용하고 있습니다. 내 질문의 설명을 변경했습니다.

이 글에서 AndreyT 는 컴파일러가 그러한 입력에서 동작하는 방법과이 최소 정수가 어떻게 구현되었는지에 대해 매우 자세하게 설명했습니다. 반면qPCR4vir 는 관련된 "호기심"과 정수 표현 방법을 제시했습니다. 너무 인상적입니다!


-2147483648"숫자"가 아닙니다. C ++ 언어는 음수 리터럴 값을 지원하지 않습니다.

-2147483648실제로는 표현식입니다. 앞에 2147483648단항 -연산자가 있는 양수 리터럴 값 입니다 . 플랫폼 2147483648에서 긍정적 인 int범위에 비해 이 너무 큽니다 . 유형 long int이 플랫폼에서 더 큰 범위를 가지면 컴파일러 2147483648long int유형 있다고 가정해야 합니다. (C ++ 11에서는 컴파일러도 long long int형식 을 고려해야 합니다.) 이렇게하면 컴파일러가 -2147483648더 큰 형식의 도메인에서 평가하게 되고 결과는 예상대로 음수가됩니다.

그러나 분명히 귀하의 경우 범위는의 범위 long int와 동일하며 int일반적으로 int플랫폼 보다 범위가 큰 정수 유형이 없습니다 . 이것은 공식적으로 양의 상수가 2147483648사용 가능한 모든 부호있는 정수 유형을 오버플로한다는 것을 의미하며, 이는 프로그램의 동작이 정의되지 않았 음을 의미합니다. (언제든지 언어 사양이 진단 메시지를 요구하는 대신 정의되지 않은 동작을 선택하는 것은 약간 이상하지만, 그 방법이 맞습니다.)

실제로, 행동이 정의되지 않았다는 점을 고려하면, 2147483648단항을 -적용한 후에는 긍정적으로 변하는 구현에 따른 부정적인 값으로 해석 될 수 있습니다. 또는 일부 구현에서는 값을 나타 내기 위해 부호없는 유형을 사용하려고 시도 할 수 있습니다 (예 : C89 / 90 컴파일러 unsigned long int에서는 C99 또는 C ++에서는 사용 하지 않아야 함). 어쨌든 행동은 정의되지 않았기 때문에 구현은 무엇이든 할 수 있습니다.

참고로, 이것이 상수 INT_MIN가 일반적으로 다음과 같이 정의되는 이유입니다.

#define INT_MIN (-2147483647 - 1)

더 직설적으로 보이는 대신

#define INT_MIN -2147483648

후자는 의도 한대로 작동하지 않습니다.


컴파일러 (VC2012)는 값을 보유 할 수있는 "최소"정수로 승격합니다. 첫 번째 경우, signed int(그리고 long int)는 (부호가 적용되기 전에) 수는 없지만, unsigned int할 수 있습니다 2147483648있다unsigned int ???? 유형. 두 번째에서는 강제 int으로부터 unsigned.

const bool i= (-2147483648 > 0) ;  //   --> true

경고 C4146 : 부호없는 유형에 단항 빼기 연산자 적용 , 결과는 여전히 부호 없음

관련 "호기심"은 다음과 같습니다.

const bool b= (-2147483647      > 0) ; //  false
const bool i= (-2147483648      > 0) ; //  true : result still unsigned
const bool c= ( INT_MIN-1       > 0) ; //  true :'-' int constant overflow
const bool f= ( 2147483647      > 0) ; //  true
const bool g= ( 2147483648      > 0) ; //  true
const bool d= ( INT_MAX+1       > 0) ; //  false:'+' int constant overflow
const bool j= ( int(-2147483648)> 0) ; //  false : 
const bool h= ( int(2147483648) > 0) ; //  false
const bool m= (-2147483648L     > 0) ; //  true 
const bool o= (-2147483648LL    > 0) ; //  false

C ++ 11 표준 :

2.14.2 정수 리터럴 [lex.icon]

정수 리터럴은 마침표 나 지수 부분이없는 일련의 숫자입니다. 정수 리터럴에는 기본을 지정하는 접 두부와 유형을 지정하는 접미 부가있을 수 있습니다.

정수 리터럴의 유형은 해당 값을 표시 할 수있는 해당 목록 중 첫 번째입니다.

여기에 이미지 설명을 입력하십시오

정수 리터럴을 목록에서 어떤 유형으로도 표현할 수없고 확장 정수 유형 (3.9.1)이 해당 값을 나타낼 수 있으면 해당 확장 정수 유형을 가질 수 있습니다. 리터럴에 대한 목록의 모든 유형이 서명 된 경우 확장 정수 유형이 서명됩니다. 리터럴에 대한 목록의 모든 유형이 부호가없는 경우 확장 정수 유형은 부호가 없습니다. 목록에 부호있는 유형과 부호없는 유형이 모두 있으면 확장 정수 유형에 부호가 있거나 부호가 없을 수 있습니다. 변환 단위 중 하나에 허용 된 유형으로 표현할 수없는 정수 리터럴이 포함 된 경우 프로그램이 잘못 구성됩니다.

그리고 이것은 표준의 정수에 대한 승격 규칙입니다.

4.5 통합 프로모션 [conv.prom]

이외 정수형의 prvalue bool, char16_t, char32_t, 또는 wchar_t그 정수 변환 계수 (4.13) 이하 INT의 랭크를 초과 유형의 prvalue로 전환 될 수 int있는 경우 int, 소스 타입의 모든 값을 나타낼 수있다; 그렇지 않으면 소스 prvalue를 유형의 prvalue로 변환 할 수 있습니다 unsigned int.


요컨대,으로 2147483648오버 플로우 -2147483648하고 (-(-2147483648) > 0)입니다 true.

이것은2147483648 바이너리에서 어떻게 생겼는지입니다.

또한 부호있는 이진 계산의 경우 최상위 비트 ( "MSB")는 부호 비트입니다. 이 질문 은 이유를 설명하는 데 도움 될 수 있습니다.


때문에 -2147483648실제로 2147483648부정과 ( -)에 적용된 숫자는 당신이 기대되지 않는 것. 실제로이 의사 코드와 같습니다.operator -(2147483648)

지금, 당신의 컴파일러를 가정하는 것은이 sizeof(int)동일 4CHAR_BIT같이 정의된다 8즉 만들 것, 2147483648정수의 최대 부호있는 값을 오버 플로우 ( 2147483647). 최대 + 1은 무엇입니까? 4 비트, 2s 칭찬 정수로이를 해결할 수 있습니다.

기다림! 8은 정수를 오버플로합니다! 우리는 무엇을해야합니까? 1000비트 의 부호없는 표현을 사용하고 비트를 부호있는 정수로 해석하십시오. 이 표현은 우리 가 모두 알고 있듯이 -82s 보수 부정을 적용하여 8우리보다 큽니다 0.

이것은 왜 <limits.h>(와 <climits>) 일반적 정의 INT_MIN((-2147483647) - 1)- 최대 부호있는 정수가 (그래서 0x7FFFFFFF) (부정한다 0x80000001), 다음 감소 ( 0x80000000).

참고 URL : https://stackoverflow.com/questions/14695118/2147483648-0-returns-true-in-c

반응형