IT TIP

부호있는 / 부호없는 비교

itqueen 2020. 10. 14. 21:32
반응형

부호있는 / 부호없는 비교


다음 코드가 표시된 장소에서 경고를 표시하지 않는 이유를 이해하려고합니다.

//from limits.h
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
#define INT_MAX  2147483647 /* maximum (signed) int value */
            /* = 0x7fffffff */

int a = INT_MAX;
//_int64 a = INT_MAX; // makes all warnings go away
unsigned int b = UINT_MAX;
bool c = false;

if(a < b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a > b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a <= b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a >= b) // warning C4018: '<' : signed/unsigned mismatch
    c = true;
if(a == b) // no warning <--- warning expected here
    c = true;
if(((unsigned int)a) == b) // no warning (as expected)
    c = true;
if(a == ((int)b)) // no warning (as expected)
    c = true;

배경 홍보와 관련이 있다고 생각했는데 마지막 두 사람은 그렇지 않은 것 같습니다.

내 생각에, 첫 번째 ==비교는 다른 것만 큼 서명 / 부호없는 불일치입니까?


부호있는 값과 부호없는 값을 비교할 때 컴파일러는 부호있는 값을 부호없는 값으로 변환합니다. 평등을 위해 이것은 중요하지 않습니다 -1 == (unsigned) -1. 다른 비교의 경우 중요합니다. 예를 들어 다음이 참 -1 > 2U입니다..

편집 : 참조 :

5/9 : (표현식)

산술 또는 열거 유형의 피연산자를 예상하는 많은 이항 연산자는 유사한 방식으로 변환을 일으키고 결과 유형을 산출합니다. 목적은 결과의 유형이기도 한 공통 유형을 생성하는 것입니다. 이 패턴을 일반적인 산술 변환이라고하며 다음과 같이 정의됩니다.

  • 피연산자가 long double 유형이면 다른 피연산자는 long double로 변환됩니다.

  • 그렇지 않으면 피연산자가 double이면 다른 피연산자가 double로 변환됩니다.

  • 그렇지 않으면 피연산자가 float이면 다른 피연산자는 float로 변환됩니다.

  • 그렇지 않으면 적분 프로모션 (4.5)이 두 피연산자 모두에서 수행됩니다 .54)

  • 그런 다음 피연산자가 unsigned long이면 다른 피연산자는 unsigned long으로 변환됩니다.

  • 그렇지 않고 한 피연산자가 long int이고 다른 하나는 unsigned int이면 long int가 unsigned int의 모든 값을 나타낼 수 있으면 unsigned int는 long int로 변환됩니다. 그렇지 않으면 두 피연산자가 unsigned long int로 변환됩니다.

  • 그렇지 않으면 피연산자가 길면 다른 피연산자가 long으로 변환됩니다.

  • 그렇지 않으면 피연산자가 부호가 없으면 다른 피연산자가 부호 없음으로 변환됩니다.

4.7 / 2 : (통합 변환)

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

EDIT2 : MSVC 경고 수준

What is warned about on the different warning levels of MSVC is, of course, choices made by the developers. As I see it, their choices in relation to signed/unsigned equality vs greater/less comparisons make sense, this is entirely subjective of course:

-1 == -1 means the same as -1 == (unsigned) -1 - I find that an intuitive result.

-1 < 2 does not mean the same as -1 < (unsigned) 2 - This is less intuitive at first glance, and IMO deserves an "earlier" warning.


Why signed/unsigned warnings are important and programmers must pay heed to them, is demonstrated by the following example.

Guess the output of this code?

#include <iostream>

int main() {
        int i = -1;
        unsigned int j = 1;
        if ( i < j ) 
            std::cout << " i is less than j";
        else
            std::cout << " i is greater than j";

        return 0;
}

Output:

i is greater than j

Surprised? Online Demo : http://www.ideone.com/5iCxY

Bottomline: in comparison, if one operand is unsigned, then the other operand is implicitly converted into unsigned if its type is signed!


The == operator just does a bitwise comparison (by simple division to see if it is 0).

The smaller/bigger than comparisons rely much more on the sign of the number.

4 bit Example:

1111 = 15 ? or -1 ?

so if you have 1111 < 0001 ... it's ambiguous...

but if you have 1111 == 1111 ... It's the same thing although you didn't mean it to be.


In a system that represents the values using 2-complement (most modern processors) they are equal even in their binary form. This may be why compiler doesn't complain about a == b.

And to me it's strange compiler doesn't warn you on a == ((int)b). I think it should give you an integer truncation warning or something.

참고URL : https://stackoverflow.com/questions/5416414/signed-unsigned-comparisons

반응형