简体   繁体   中英

unsigned int (c++) vs uint (c#)

Following is the c# code:

   static void Main(string[] args)
    {
        uint y = 12;
        int x = -2;
        if (x > y)
            Console.WriteLine("x is greater");
        else
            Console.WriteLine("y is greater");
    }

and this is c++ code:

int _tmain(int argc, _TCHAR* argv[])
{
unsigned int y = 12;
int x = -2;
if(x>y)
    printf("x is greater");
else
    printf("y is greater");

return 0;
}

Both are giving different result. Am I missing something basic? Any idea?

C++ and C# are different languages. They have different rules for handling type promotion in the event of comparisons.

In C++ and C, they're usually compared as if they were both unsigned. This is called "unsigned preserving". C++ and C compilers traditionally use "unsigned preserving" and the use of this is specified in the C++ standard and in K&R.

In C#, they're both converted to signed longs and then compared. This is called "value preserving". C# specifies value preserving.

ANSI C also specifies value preserving, but only when dealing with shorts and chars. Shorts and chars (signed and unsigned) are upconverted to ints in a value-preserving manner and then compared. So if an unsigned short were compared to a signed short, the result would come out like the C# example. Any time a conversion to a larger size is done, it's done in a value-preserving manner, but if the two variables are the same size (and not shorts or chars) and either one is unsigned, then they get compared as unsigned quantities in ANSI C. There's a good discussion of the up and down sides of both approaches in the comp.lang.c FAQ .

In C++, when you compare an unsigned int and a signed int , the signed int is converted to unsigned int . Converting a negative signed int to an unsigned int is done by adding UINT_MAX + 1 , which is larger than 12 and hence the result.

In C#, if you are getting the opposite result then it means that in C# both the expressions are being converted to signed int signed long ( long or System.Int64 ) 1 and then compared.

In C++, your compiler must have given you the warning:

warning: comparison between signed and unsigned integer expressions

Rule:
Always take warnings emitted by the compiler seriously!

1 As rightly pointed out by svick in comments.

I don't know about the standard of C#, but in the C++ standard, usual arithmetic conversions would be applied to both operands of relational operators:

 [......enum, floating point type involed......] — Otherwise, the integral promotions (4.5) shall be performed on both operands. Then the following rules shall be applied to the promoted operands: — If both operands have the same type, no further conversion is needed. — Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank. — Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type. — Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type. — Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type. 

Thus, when unsigned int is compared with int , int would be converted to unsigned int , and -2 would become a very large number when converted to unsigned int .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM