부호없는 변수에 음수 값을 할당하면 어떻게됩니까?


82

부호없는 변수에 음수 값을 할당하면 어떻게 될지 궁금했습니다.

코드는 다음과 같습니다.

unsigned int nVal = 0;
nVal = -5;

컴파일러 오류가 발생하지 않았습니다. 프로그램을 실행할 때 nVal이상한 값이 할당되었습니다! 2의 보수 값이 할당되는 것일 수 nVal있습니까?


1
내 직감 (아직 표준에서 찾을 수 없었 음)은 동작이 기술적으로 정의되지 않았다는 것입니다. 게다가, 나는 당신이 찾을 수있는 거의 모든 컴파일러에서 당신이 기대하는 것을 보게 될 것이라고 생각합니다. 따라서 일반적으로 그 행동을 볼 수 있지만 그것에 의지하는 것은 좋은 생각이 아닙니다.
sblom

6
정의되지 않은 것은 아니지만 ( §4.7 / 2 참조 ), 표현 (예 : 2의 보수)은 표준에 의해 요구되지 않습니다.
Georg Fritzsche

@gf (아래 등), 멋지다. 실제로 동작이 예상 한대로 명시 적으로 정의 된 것 같습니다. @viswanathan.
sblom

3
두 번째 줄은 nVal = (unsigned int) -5;. 의 캐스팅 -5에이 unsigned int되는 정의 6.3.1.3에서. 2s 보수의 표현은 표준에 의해 의무화되지 않지만 부호없는 것으로 변환하는 알고리즘은 다음과 같습니다. "값이 범위 내에있을 때까지 newtype에서 표현할 수있는 최대 값보다 하나 더 많은 값을 반복적으로 더하거나 빼서 값을 변환합니다. 새로운 유형의. "
Pascal Cuoq

1
@Pascal : C99를 언급하는 것 같지만 질문은 C ++ 태그입니다.
Georg Fritzsche

답변:


67

공식 답변-섹션 4.7 conv.integral

대상 유형은 부호가 "결과 값은 소스 정수 최소 부호없는 정수 합치는 (모듈로 2 Nn . 2의 보수 표현이 변환 [참고 인 부호 타입을 나타내는 데 사용되는 비트 수) 개념적이며 비트 패턴에 변화가 없습니다 (잘림이없는 경우).

이것은 본질적으로 기본 아키텍처가 2의 보수가 아닌 메서드 (예 : 부호있는 크기 또는 1의 보수)에 저장하는 경우 부호없는 변환이 2의 보수 인 것처럼 동작해야 함을 의미합니다.


37
소스 정수에 합동하는 최소 부호없는 정수 는 무엇을 의미합니까?
David Rodríguez-dribeas 2013-04-04

11
@ DavidRodríguez-dribeas 예를 들어, 5 % 2와 3 % 2는 모두 1이기 때문에 5와 3은 "합동 모드 2"입니다.
JoeQuery

어떤 버전의 C ++ 표준과 관련이 있습니까? 모두?
Alexey Kruglov

36

unsigned int에 -5 (2의 보수)를 나타내는 비트 패턴을 할당합니다. 큰 부호없는 값이됩니다. 32 비트 정수의 경우 2 ^ 32-5 또는 4294967291입니다.


2
비트는 그것과 아무 관련이 없습니다.
GManNickG

1
@BenVoigt : 충분히 공평합니다. 비트가 해석되는 방식과는 아무 관련이 없음을 의미했습니다. (즉, 인용 된 부분의 "비트"는을 (를 ceil(log_2(x))) 위한 축약 형입니다 .)
GManNickG

1
@GManNickG 비트 (비트에 속함)? 2 's Compliment (정말 친절합니다) ? GAAAAAAAAAAAAAH!
NullUserException

1
@NullUserException : 하하, 알아. 단지 "* s"대신 "*"를 쓰는 것은 제가 한동안 가지고 있었던 끔찍한 습관입니다. 보완이 아닌 칭찬에 관해서는 그것은 순수한 어리 석음입니다. :)
GManNickG

단순성이 핵심입니다. 이 대답에는 그것이 있습니다. (2 ^ 32-5) 문서를 인용하는 것보다이 동작을 더 잘 설명합니다.
Redhart

4

최대 부호없는 정수-4 값의 양의 정수로 표시됩니다 (값은 컴퓨터 아키텍처 및 컴파일러에 따라 다름).

BTW
간단한 C ++ "hello world"유형 프로그램을 작성하여이를 확인하고 직접 확인할 수 있습니다.


나는 그것이 내가 질문 한 이유를 작성하고 확인했지만 컴파일러가 어떻게 그 양의 값에 도달했는지 몰랐습니다. 감사합니다
ckv

6
불행히도 C ++에서는 동작을 테스트하는 프로그램을 작성하는 것이 항상 좋은 생각은 아닙니다. 예를 들어 서명 된 오버플 로의 경우 어떤 일이 발생하는지 테스트하려고하면 정의되지 않은 동작이 발생하며 모든 컴퓨터 / 컴파일러에서 동일하다고 보장 할 수 없습니다.
Ben Jones

4

맞습니다. 부호있는 정수는 2의 보수 형식으로 저장되고 부호없는 정수는 부호없는 이진 표현에 저장됩니다 . C (및 C ++)는 둘을 구분하지 않으므로 최종 값은 단순히 2의 보수 이진 표현의 부호없는 이진 값입니다.


16
2의 칭찬에 저장되지 않을 수 있습니다.
GManNickG

무언가가 "2에 저장"되었다는 것은 무엇을 의미합니까? @GManNickG
JeremyF

4
@JeremyF : "2", "2의 칭찬"이 아닙니다. Google에서 사용할 수있는 용어이며 부호있는 정수를 나타내는 방법입니다.
GManNickG 2014 년

2

네, 맞습니다. 할당 된 실제 값은 세 번째를 제외한 모든 비트 세트와 유사합니다. -1은 모든 비트 세트 (16 진수 : 0xFFFFFFFF), -2는 첫 번째 비트를 제외한 모든 비트입니다. 당신이 보게 될 것은 아마도 10 진수로 4294967291에 해당하는 16 진수 값 0xFFFFFFFB 일 것입니다.


3
비트는 그것과 관련이 없으며 정수 표현이 지정되지 않았습니다.
GManNickG

2
당신의 대답은 정확하고 엄격하며 내가 수업에서 결코 사용하지 않을 것입니다.
Martin

-5의 2의 보수에 대한 내 대답을 참조하십시오. 여기 이진 값에 대해 수학을 올바르게 수행했다고 생각하지 않습니다.
cynistersix

0

부호없는 변수에 음수 값을 할당하면 2의 보수 방법을 사용하여 처리하고이 방법에서는 모든 0을 1로, 모든 1을 0으로 뒤집은 다음 1을 더합니다. 귀하의 경우에는 4 바이트 (32 비트) 인 int를 다루고 있으므로 32 비트 숫자에 2의 보수 방법을 사용하여 더 높은 비트를 뒤집습니다. 예를 들면 :

┌─[student@pc]─[~]
└──╼ $pcalc 0y00000000000000000000000000000101      # 5 in binary
        5                       0x5                     0y101
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010      # flip all bits  
      4294967290      0xfffffffa      0y11111111111111111111111111111010
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010 + 1  # add 1 to that flipped binarry
      4294967291      0xfffffffb      0y11111111111111111111111111111011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.