부호없는 정수 빼기가 정의 된 동작입니까?
결과가 음수 일 때 동일한 유형의 다른 정수에서 부호없는 정수를 빼는 데 문제가 있다고 생각하는 사람의 코드를 보았습니다. 따라서 이와 같은 코드는 대부분의 아키텍처에서 작동하더라도 올바르지 않습니다.
unsigned int To, Tf;
To = getcounter();
while (1) {
Tf = getcounter();
if ((Tf-To) >= TIME_LIMIT) {
break;
}
}
이것은 내가 찾을 수있는 C 표준에서 모호하게 관련된 유일한 인용문입니다.
부호없는 피연산자를 포함하는 계산은 결과로 나타나는 부호없는 정수 형식으로 나타낼 수없는 결과가 결과 형식으로 나타낼 수있는 가장 큰 값보다 하나 더 큰 수의 모듈로 축소되기 때문에 절대로 초과 될 수 없습니다.
나는 오른쪽 피연산자가 더 클 때 연산이 모듈로 잘린 숫자의 맥락에서 의미가 있도록 조정된다는 것을 의미하는 따옴표를 취할 수 있다고 가정합니다.
즉
0x0000-0x0001 == 0x 1 0000-0x0001 == 0xFFFF
구현 종속 서명 의미를 사용하는 것과 반대 :
0x0000-0x0001 == (부호 없음) (0 + -1) == (0xFFFF뿐만 아니라 0xFFFE 또는 0x8001)
어떤 해석이 맞습니까? 전혀 정의되어 있습니까?
부호없는 유형에서 음수를 생성하는 빼기 결과는 잘 정의되어 있습니다.
- [...] 부호없는 피연산자를 포함하는 계산은 결과 형식으로 나타낼 수있는 가장 큰 값보다 하나 더 큰 수만큼 부호없는 정수 형식으로 표시 할 수없는 결과가 축소되므로 절대 오버플로 할 수 없습니다. (ISO / IEC 9899 : 1999 (E) §6.2.5 / 9)
보시다시피, (unsigned)0 - (unsigned)1
모듈로 UINT_MAX + 1, 즉 UINT_MAX와 같습니다.
"부호없는 피연산자를 포함하는 계산은 절대 오버플로 할 수 없습니다"라고 표시되어있어 상한을 초과하는 경우에만 적용된다고 믿게 만들 수 있지만 이는 문장의 실제 바인딩 부분에 대한 동기 로 제시됩니다 . "a 결과적으로 부호없는 정수 유형으로 표현할 수없는 결과는 결과 유형으로 나타낼 수있는 가장 큰 값보다 하나 더 큰 수의 모듈로 축소됩니다. " 이 구는 유형의 상한의 오버플로에 제한되지 않으며 표현하기에는 너무 낮은 값에도 동일하게 적용됩니다.
부호없는 유형으로 작업 할 때 모듈 식 산술 ( "둘러싸 기" 동작 이라고도 함 )이 발생합니다. 이 모듈 식 산술 을 이해하려면 다음 시계를 살펴보십시오.
9 + 4 = 1 ( 13 mod 12 )이므로 다른 방향으로는 1-4 = 9 ( -3 mod 12 )입니다. 서명되지 않은 유형으로 작업하는 동안에도 동일한 원칙이 적용됩니다. 상기 중간 결과 유형 인 unsigned
후 모듈러 산술 일어난다.
이제 결과를 저장하는 다음 작업을 살펴보십시오 unsigned int
.
unsigned int five = 5, seven = 7;
unsigned int a = five - seven; // a = (-2 % 2^32) = 4294967294
int one = 1, six = 6;
unsigned int b = one - six; // b = (-5 % 2^32) = 4294967291
When you want to make sure that the result is signed
, then stored it into signed
variable or cast it to signed
. When you want to get the difference between numbers and make sure that the modular arithmetic will not be applied, then you should consider using abs()
function defined in stdlib.h
:
int c = five - seven; // c = -2
int d = abs(five - seven); // d = 2
Be very careful, especially while writing conditions, because:
if (abs(five - seven) < seven) // = if (2 < 7)
// ...
if (five - seven < -1) // = if (-2 < -1)
// ...
if (one - six < 1) // = if (-5 < 1)
// ...
if ((int)(five - seven) < 1) // = if (-2 < 1)
// ...
but
if (five - seven < 1) // = if ((unsigned int)-2 < 1) = if (4294967294 < 1)
// ...
if (one - six < five) // = if ((unsigned int)-5 < 5) = if (4294967291 < 5)
// ...
Well, the first interpretation is correct. However, your reasoning about the "signed semantics" in this context is wrong.
Again, your first interpretation is correct. Unsigned arithmetic follow the rules of modulo arithmetic, meaning that 0x0000 - 0x0001
evaluates to 0xFFFF
for 32-bit unsigned types.
However, the second interpretation (the one based on "signed semantics") is also required to produce the same result. I.e. even if you evaluate 0 - 1
in the domain of signed type and obtain -1
as the intermediate result, this -1
is still required to produce 0xFFFF
when later it gets converted to unsigned type. Even if some platform uses an exotic representation for signed integers (1's complement, signed magnitude), this platform is still required to apply rules of modulo arithmetic when converting signed integer values to unsigned ones.
For example, this evaluation
signed int a = 0, b = 1;
unsigned int c = a - b;
is still guaranteed to produce UINT_MAX
in c
, even if the platform is using an exotic representation for signed integers.
유형의 부호 숫자 unsigned int
이상, 형식 변환의 부재에 a-b
첨가 할 때, 부호 번호 수득 같이 정의된다 b
,을 산출 할 것이다 a
. 음수를 부호없는 숫자로 변환하는 것은 부호가 반전 된 원래 숫자에 더 해지면 0이되는 숫자를 산출하는 것으로 정의됩니다 (따라서 -5를 부호없는 숫자로 변환하면 5에 더 해지면 0이되는 값이 산출됩니다). .
더 작은 부호없는 숫자 는 빼기 전에 unsigned int
입력하도록 승격 될 수 int
있으며의 동작은 a-b
의 크기에 따라 달라집니다 int
.
참고 URL : https://stackoverflow.com/questions/7221409/is-unsigned-integer-subtraction-defined-behavior
'IT story' 카테고리의 다른 글
++ xa lvalue 및 x ++가 rvalue 인 이유는 무엇입니까? (0) | 2020.08.31 |
---|---|
C ++ 상수 사용법 설명 (0) | 2020.08.31 |
Python에서 첫 번째 문자열 교체 (0) | 2020.08.31 |
(LINQ / Predicate)를 사용하여 DataTable의 모든 열 이름을 문자열 배열로 가져옵니다. (0) | 2020.08.31 |
깨지지 않는 공백은 JavaScript 문자열에서 어떻게 표현됩니까? (0) | 2020.08.31 |