2016-07-10 3 views
1

나는 보았다 -0x80000000 + -0x80000000 = 0이 나에게 이해가되지 않았다 그래서 나는 간단한 C 프로그램은 아래의 테스트하고 참으로 답이 0 썼다 :왜 -0x80000000 + -0x80000000 == 0입니까? programmign 트릭에 대한 책을 읽는 동안

#include <stdio.h> 

int main() 
{ 
    int x = -0x80000000; 
    int y = -0x80000000; 

    int z = x + y; 

    printf("Z is: %d", z); 
    return 0; 
} 

아무도 그 이유를 밝힐 수 있습니까? 오버플로에 대해 뭔가를 봤지만 오버플로가 예외 또는 다른 오류가 아닌 0을 초래하는 방식을 볼 수 없습니다. 나는 어떤 경고 나 아무것도 얻지 않는다.

+1

예, 오버플로가 발생합니다. 아니요, C는 일반적으로 정수 오버플로에 대해 경고하거나 예외를 throw하지 않습니다. 실제 응답의 하위 32 비트가 모두 0이기 때문에 0이 표시되고, 정수 오버플로가 발생하면 4294967296 모듈로, 즉 모듈로 2^32를 얻는 경향이 있습니다. –

답변

2

부호있는 정수의 정확한 표현이 정의되어 있지 않기 때문에 여기에서 발생하는 부호있는 정수 오버플로는 undefined behavior입니다.

그러나 실제로 대부분의 기계는 부호있는 정수에 대해 2의 보수 표현을 사용하며,이 특정 프로그램은이를 이용합니다.

0x80000000은 부호없는 정수입니다. -은 부호를 부호로 변경하여이를 무효화합니다. int이 시스템에서 32 비트라고 가정하면이 값은 여전히 ​​적합합니다. 사실, 서명 된 32 비트 int이 보유 할 수있는 가장 작은 값이며이 숫자의 16 진수 표현은 0x80000000입니다.

2의 보수 표현에 숫자를 추가 할 때 기호에 대해 걱정할 필요가없는 기능이 있습니다. 부호없는 숫자와 정확히 같은 방식으로 추가됩니다. 우리가 xy를 추가 할 때

그래서, 우리는이를 얻을 : 시스템에 int 32 비트입니다

0x80000000 
+ 0x80000000 
------------- 
    0x100000000 

때문에, 단지 가장 낮은 32 비트는 유지됩니다. 그리고 비트의 가치는 0입니다.

다시 말하지만 이것은 실제로 정의되지 않은 동작입니다. 이 코드는 부호있는 정수에 2의 보수 표현을 사용하고 int이 32 비트이기 때문에 작동합니다. 이것은 대부분의 기계/컴파일러에 공통적이지만 전부는 아닙니다.

+1

'0x80000000'의 타입은 구현으로 정의됩니다. 서명 될 수 있습니다. – 2501

+2

서명되지 않은 형식을 단순히 부정하면 서명 된 형식이 산출되지 않습니다. 일부 가정 하에서, OP의 경우, 부호없는 값은 (양의) 값 0x80000000으로 되돌아갑니다. – 2501

+0

감사합니다. 무슨 일이 일어나는지 이해하도록 도와 줬습니다. – MHartley

1

구현에 정의 된 동작이 많으므로 런타임에 정의되지 않은 동작이 발생할 가능성이 큽니다. 그 이상은 귀하 및 서적 작가 건축에 대한 세부 정보 없이는 알 수 없습니다.

추가 정보 없이는 결과가 의미가 없습니다. 명확한 답을 원한다면 아키텍처의 유형 범위를 확인하고 할당 및 산술 결과가 해당 유형에 맞는지 확인하십시오.