2009-09-12 3 views
8

나는 이것을 얻지 못한다! 모두가 실패하거나 둘 다 안 어느부호없는 길이 0 <-1?

s1 < s2-1 

:

#include <stdio.h> 

int main() 
{ 
    unsigned short t1 = 0, t2 = 0; 

    if(t1 < t2-1) 
     printf(" t1 < t2-1\n"); 

    unsigned long s1 = 0, s2 = 0; 

    if(s1 < s2-1) 
     printf(" s1 < s2-1\n"); 
} 

이 발생합니다. 나는 gcc와 함께 이것을 시도했다 & 4.2

+0

~ nairboon : 편집 하시길 바랍니다. 내가 대신 작성한 코드는 기능적으로 동일하지만 편집기로 복사/붙여 넣기가 가능하며 변경없이 컴파일 할 수 있습니다. –

+1

이 결과는 결과가 보장되지 않습니다. int가 short와 같은 값의 범위를 저장하는 머신에서 (16 비트 머신은 생각할 것입니다.), 양쪽 모두에 대해 출력이 표시됩니다. 왜냐하면 프로모션이 int가 아닌 unsigned int로 변환되기 때문입니다. –

답변

12

C 언어는 많은 사업자에 대해 "일반적인 산술 변환"을 수행 - 변환은 C99 표준의 6.3.1.8에 요약되어 있습니다. 정수형 피연산자의 경우 첫 번째 프로모션이 수행되며 이는 사용자의 문제를 유발합니다. int로 원래 유형의 모든 값을 나타낼 수있는 경우

, 값은 변환됩니다 : 프로모션은 다른 것들 사이 말한다 (산술 연산자/부울, 문자 및 정수), 6.3.1.1에 설명되어 있습니다 int; 그렇지 않으면 unsigned int로 변환됩니다. 이것을 정수 승격이라고합니다. 다른 모든 유형은 정수 승격에 의해 변경되지 않습니다.

프로모션은 intunsigned int 및 (또는 비트 필드)보다 낮은 순위 정수형 개체 또는 식에만 적용된다. 그래서 exression에

:

t1 < t2-1 

변수들이 플랫폼에 intunsigned short의 모든 값을 나타낼 수 있기 때문에, int로 승진 unsigned short에도 불구하고. 따라서 표현식은 int 유형을 사용하여 계산되며 언더 플로우는 발생하지 않습니다. 표현식의 t2-1 부분은 음수 1로 끝납니다.식에

는 : 그들이 int/ unsigned int보다 더 높은 '순위'를 가지고 있기 때문에 표현이에서 언더 플로로 (부호없는 산술을 사용하여 평가되도록

s1 < s2-1 

unsigned long 유형이 촉진되지 않는다 빼기) s2-1 부 표현식은 음수가 아닌 매우 큰 수로 평가됩니다.

설명에 litb가 표시되어있는 경우 플랫폼에 int이 구현 된 경우 (허용되는 경우 - MS-DOS 용) 예), 프로 intunsigned short (unsigned short은 16 비트 이상이어야 함)의 모든 값을 나타낼 수 없으므로 unsigned short의 동작은 int 대신에 unsigned int이됩니다. 이 경우 if 문은 모두 참으로 평가됩니다.

13

Iam 확실하지는 않지만 표현식 t2-1이 자동으로 int 값으로 확장되었다고 생각된다. 여기에 정확한 변환 규칙이있는 C 표준이 없지만 int보다 작은 유형이 자동으로 확장됩니다.

+3

+1, 산술 표현식에서 유형 (부호가 있거나 부호가없는) 짧은 객체 및 (부호가 있거나 부호가없는 /) 문자는 *로 * 승격됩니다. – avakar

+1

이 답변은 **'t2' **가 **'t2-1' **이 아닌 int로 변환 되었다면 더 좋을 것입니다. (따라서 변환이 * 빼기 이전에 일어 났음을 분명히 알 수 있습니다). –

3

다른 유형 사이에서 작동 할 때마다 발견되는 강압이 항상 명확하지는 않습니다. t2이 u16이면 1int (아마도 32 비트)이므로 t2-1은 정확하게 "다른 유형 간의 연산"이며 결과적으로 전체 변형을 int로 만듭니다 (u16보다 "길다"). 나중에 s2와 1은 모두 32 비트이기 때문에 (서명이 다르긴하지만) 전체적인 강제는 부호없는 값으로 길어집니다. 따라서 관련된 유형의 크기는 전체적인 강압의 서명 여부를 결정하는 데 도움이됩니다.

나는 혼합 부호의 피하시기 바랍니다 캐스팅하거나 int 유형이 있으며, 여러분의 인생을 잠재적으로 복잡하고 코드가 잠재적 인자를 취하지 것 같은 1 같은 리터럴 특수 문자 표기를 통해 작업 ((또한 이상적으로 혼합 크기를!) -).

0

-1은 모두 1로 표시됩니다. 따라서 부호가없는 것으로 해석 될 때 그 값은 2^32-1이며 분명히 0보다 큽니다. 첫 번째 비교가 32 비트 부호있는 산술을 수행하도록 확장되고있는 것 같습니다 (아마도 "1"이 signed int). 비교가 지금은 다시 16 비트 부호없는 공간에서 수행되기 때문에 다음은의의 printf에 얻을 것이다

참고 :

u32 temp = t2 - 1; 
if(t1 < temp) 
    printf(" t1 < t2-1\n"); 
+4

리터럴 1 (유형 'int')은 뺄셈 전에'부호없는 long '으로 변환됩니다. 부호없는 타입에 대한 산술은 항상 타입 - 특정'k'에 대해 modulo'2^k'로 수행되기 때문에, 결과는'2^k-1'입니다. -1의 표현은 관련이 없습니다 (일부 아키텍처에서는 모든 표현 일 필요는 없습니다). – avakar

+0

-1의 표현은 두 번째 부분을 설명하는 데 사용됩니다. 부호없는 long에서는 왜 0 <-1인지 설명합니다. – Yuliy

+0

아니요. avakar가 말했듯이,'-N' -> unsigned는 순전히 수학적 연산이며, 단지'UINT_MAX + 1 - N'을 계산합니다. 어떤 표현도 어디에도 의존하지 않습니다. –

관련 문제