왜 0 < -0x80000000 인가요?
아래에 간단한 프로그램이 있습니다.
#include <stdio.h>
#define INT32_MIN (-0x80000000)
int main(void)
{
long long bal = 0;
if(bal < INT32_MIN )
{
printf("Failed!!!");
}
else
{
printf("Success!!!");
}
return 0;
}
조건if(bal < INT32_MIN )
항상 진실입니다.그게 어떻게 가능해?
매크로를 다음과 같이 변경하면 정상적으로 동작합니다.
#define INT32_MIN (-2147483648L)
누가 그 문제를 지적할 수 있나요?
이건 좀 미묘하네요.
프로그램의 모든 정수 리터럴에는 유형이 있습니다.6.4.4.1의 표에 의해 규제되는 유형은 무엇입니까?
Suffix Decimal Constant Octal or Hexadecimal Constant
none int int
long int unsigned int
long long int long int
unsigned long int
long long int
unsigned long long int
리터럴 번호가 기본값에 맞지 않는 경우int
type은 위의 표와 같이 다음으로 큰 타입을 시도합니다.따라서 정규 10진 정수 리터럴의 경우 다음과 같습니다.
- 해라
int
- 안 맞으면 해봐
long
- 안 맞으면 해봐
long long
.
하지만 16진수는 다르게 행동합니다!리터럴이 부호 있는 글씨체 안에 들어가지 않으면int
, 먼저 시도합니다.unsigned int
더 큰 활자를 시도하기 전에 말이죠.위 표의 차이를 참조하십시오.
32비트 시스템에서는 리터럴이0x80000000
종류unsigned int
.
즉, 단항식을 적용할 수 있습니다.-
서명된 정수를 오버플로 할 때와는 달리 구현 정의 동작을 호출하지 않고 리터럴에 연산자를 추가합니다.대신, 당신은 그 가치를 얻게 될 것이다.0x80000000
, 양의 값.
bal < INT32_MIN
일반적인 산술 변환과 식의 결과를 호출한다.0x80000000
에서 승격하다unsigned int
로.long long
. 값0x80000000
0은 0x80000000보다 작기 때문에 결과는 다음과 같습니다.
리터럴을 다음으로 치환하는 경우2147483648L
당신은 10진 표기를 사용하므로 컴파일러는 이 표기를 선택하지 않습니다.unsigned int
, 그러나 오히려 그것을 안에 넣으려고 합니다.long
또한 L 접미사는 당신이 원한다는 것을 나타냅니다.long
가능하다면요.L 접미사는 실제로 6.4.4.1에 기재된 표를 계속 읽으면 유사한 규칙이 있습니다.요청된 번호에 맞지 않습니다.long
32비트 케이스에서는 그렇지 않지만 컴파일러에 의해long long
딱 맞는 곳이죠
0x80000000
는 입니다.unsigned
값이 2147483648인 리터럴.
여기에 단항 마이너스(-)를 적용해도 값이 0이 아닌 부호 없는 유형이 계속 표시됩니다.(실제로 제로 이외의 값일 경우)x
최종적으로 얻을 수 있는 가치는 다음과 같습니다.UINT_MAX - x + 1
.)
이 정수 리터럴0x80000000
타입이 있다unsigned int
.
C기준(6.4.4.1 정수)에 의거한다.
5 정수 상수의 유형은 해당 값을 나타낼 수 있는 첫 번째 목록입니다.
그리고 이 정수 상수는 다음과 같은 유형으로 나타낼 수 있다.unsigned int
.
그래서 이 표현은
-0x80000000
같은 것을 가지다unsigned int
type. 게다가 같은 값을 가지고 있습니다.0x80000000
다음 방법으로 계산되는 두 개의 보완 표현에서
-0x80000000 = ~0x80000000 + 1 => 0x7FFFFFFF + 1 => 0x80000000
이것은 예를 들어 글을 쓰면 부작용이 있다.
int x = INT_MIN;
x = abs( x );
결과는 다시 나올 것이다.INT_MIN
.
따라서 이 상태에서는
bal < INT32_MIN
비교가 되다0
서명되지 않은 가치로0x80000000
일반적인 산술 변환 규칙에 따라 long long int로 변환됩니다.
0이 다음보다 작다는 것은 명백합니다.0x80000000
.
숫자 상수0x80000000
종류unsigned int
우리가 가져가면-0x80000000
2s 칭찬 계산을 하면 다음과 같은 결과가 나옵니다.
~0x80000000 = 0x7FFFFFFF
0x7FFFFFFF + 1 = 0x80000000
그렇게-0x80000000 == 0x80000000
그리고 비교.(0 < 0x80000000)
(이후로)0x80000000
is unsigned)는 참입니다.
생각하기에 혼란스러운 점이 있다.-
는 숫자 상수의 일부입니다.
아래 코드0x80000000
는 숫자 상수입니다.그것의 종류는 그것만으로 결정됩니다.그-
나중에 적용되며 유형은 변경되지 않습니다.
#define INT32_MIN (-0x80000000)
long long bal = 0;
if (bal < INT32_MIN )
꾸미지 않은 원시 숫자 상수는 양수입니다.
10진수일 경우 할당된 유형은 해당 유형을 유지하는 첫 번째 유형입니다.int
,long
,long long
.
정수가 8진수 또는 16진수일 경우 정수를 유지하는 첫 번째 유형을 가져옵니다.int
,unsigned
,long
,unsigned long
,long long
,unsigned long long
.
0x80000000
, OP 시스템에서 다음과 같은 유형을 가져옵니다.unsigned
또는unsigned long
어느 쪽이든 서명되지 않은 유형입니다.
-0x80000000
또한 0이 아닌 값이며 부호 없는 유형일 경우 0보다 큽니다.코드와 비교한 경우long long
비교의 양면에서 값은 변경되지 않습니다.0 < INT32_MIN
정말이에요.
대체 정의는 이러한 호기심 동작을 방지합니다.
#define INT32_MIN (-2147483647 - 1)
잠시 동안 환상의 땅을 걷자int
그리고.unsigned
48비트입니다.
그리고나서0x80000000
에 들어맞다int
타입도 그렇고int
.-0x80000000
음수가 되고 출력 결과가 다릅니다.
[본문으로 돌아가기]
부터0x80000000
부호 있는 타입 앞에 있는 부호 없는 타입에 들어맞습니다.그것은 보다 크기 때문입니다.some_signed_MAX
아직 안에some_unsigned_MAX
부호 없는 타입입니다.
C에는 정수 리터럴이 다음과 같은 규칙이 있습니다.signed
또는unsigned
에 적합한지에 따라 다르다signed
또는unsigned
(프로모션)에서32
-비트 머신 더 리터럴0x80000000
될 것이다unsigned
. 2의 보완:-0x80000000
이0x80000000
32비트 머신에 접속할 수 있습니다.따라서 비교는bal < INT32_MIN
사이에 있다signed
그리고.unsigned
C 규칙에 따라 비교하기 전에unsigned int
로 변환됩니다.long long
.
C11: 6.3.1.8/1:
[...] 그렇지 않으면 부호 있는 정수형을 가진 피연산자 유형이 부호 없는 정수형을 가진 피연산자 유형의 모든 값을 나타낼 수 있는 경우 부호 없는 정수형을 가진 피연산자 유형은 부호 있는 정수형을 가진 피연산자 유형으로 변환됩니다.
그러므로,bal < INT32_MIN
항상 있다true
.
언급URL : https://stackoverflow.com/questions/34182672/why-is-0-0x80000000
'programing' 카테고리의 다른 글
Vue가 하나의 submit() 메서드를 사용하는 여러 형식 (0) | 2022.07.14 |
---|---|
Java에서 null이 아닌 첫 번째 값을 얻는 방법은 무엇입니까? (0) | 2022.07.14 |
VueJs - materializecss에서 모달 트리거 (0) | 2022.07.14 |
Java Vector(및 Stack) 클래스가 구식 또는 폐지된 것으로 간주되는 이유는 무엇입니까? (0) | 2022.07.14 |
루프 출구에서는 다른 플랫폼에서는 루프 출구에서는 루프 출구에서는 루프 출구에서는 루프 출구에서는 루프 출구에서는 루프 출구에서는 루프 출구에서는 루프 출구에서는 (0) | 2022.07.14 |