2013-08-06 43 views
12

Có một cái nhìn tại mã này C:int xúc tiến để int unsigned trong C và C#

int main() 
{ 
    unsigned int y = 10; 
    int x = -2; 
    if (x > y) 
     printf("x is greater"); 
    else 
     printf("y is greater"); 
    return 0; 
} 
/*Output: x is greater.*/ 

Tôi hiểu tại sao sản lượng là x là lớn hơn, bởi vì khi máy tính so sánh cả trong số họ, x được thăng chức một loại số nguyên không dấu. Khi x được thăng lên số nguyên không dấu, -2 trở thành 65534, chắc chắn lớn hơn 10.

Nhưng tại sao trong C#, mã tương đương có cho kết quả ngược lại không?

public static void Main(String[] args) 
{ 
    uint y = 10; 
    int x = -2; 
    if (x > y) 
    { 
     Console.WriteLine("x is greater"); 
    } 
    else 
    { 
     Console.WriteLine("y is greater"); 
    } 
} 
//Output: y is greater. 
+11

Vì C# tốt hơn? : D – lukegravitt

+1

Tôi vừa học được điều gì đó mới về C ngày hôm nay. Tôi phải thừa nhận tôi không thích nó. Liệu trình biên dịch, ít nhất, đưa ra một cảnh báo? –

+2

bản sao có thể có của [unsigned int (C++) vs uint (C#)] (http://stackoverflow.com/questions/8266089/unsigned-int-c-vs-uint-c) – lukegravitt

Trả lời

19

Trong C#, cả uintint được thăng tiến đến một long trước khi so sánh.

này được ghi chép lại trong 4.1.5 Integral types của C đặc tả # ngôn ngữ:

Đối với nhị phân +, -, *, /,%, &, ^, |, ==, =,>, <,! > =, và < = toán tử, toán hạng được chuyển thành kiểu T, trong đó T là đầu tiên của int, uint, long và ulong có thể biểu thị đầy đủ tất cả các giá trị có thể có của cả hai toán hạng. Thao tác này sau đó được thực hiện bằng cách sử dụng độ chính xác của loại T, và loại kết quả là T (hoặc bool cho các toán tử quan hệ). Nó không được phép cho một toán hạng được loại dài và khác là loại ulong với các toán tử nhị phân.

Kể từ long là loại đầu tiên mà hoàn toàn có thể đại diện cho tất cả intuint các giá trị, các biến đều chuyển đổi sang long, sau đó so sánh.

8

Trong C#, khi so sánh giữa int và uint, cả hai giá trị đều được thăng cấp thành giá trị dài.

"Nếu không, nếu toán hạng là loại uint và toán hạng khác có kiểu sbyte, ngắn hoặc int, cả hai toán hạng sẽ được chuyển thành loại dài."

http://msdn.microsoft.com/en-us/library/aa691330(v=vs.71).aspx

0

C và C# có các quan điểm khác nhau về những loại tích phân thể hiện. Xem câu trả lời của tôi https://stackoverflow.com/a/18796084/363751 để biết một số cuộc thảo luận về chế độ xem của C. Trong C#, cho dù số nguyên đại diện cho số hoặc thành viên của vòng đại số trừu tượng được xác định ở một mức độ nào đó bằng cách "bật số học" được bật hay tắt, nhưng điều đó chỉ đơn giản là kiểm soát liệu tính toán ngoài giới hạn có nên ném ngoại lệ hay không. Nói chung, khung công tác .NET liên quan đến tất cả các kiểu số nguyên đại diện cho các số nguyên, và ngoài việc cho phép một số tính toán ngoài phạm vi được thực hiện mà không có ngoại lệ C#.

Nếu các loại chưa ký đại diện cho các thành viên của vòng đại số, hãy thêm ví dụ: -5 đến một unsigned 2 nên mang lại một giá trị unsigned mà, khi thêm vào 5, sẽ mang lại 2. Nếu chúng đại diện cho số, sau đó thêm một -5 đến một unsigned 2 nên nếu có thể mang lại một đại diện của số -3. Kể từ khi thúc đẩy các toán hạng đến Int64 sẽ cho phép điều đó xảy ra, đó là những gì C# làm. Một cách ngẫu nhiên, tôi không thích các quan niệm mà các toán tử (đặc biệt là các toán tử quan hệ!) Phải luôn hoạt động bằng cách quảng bá các toán hạng của chúng thành một kiểu tương thích chung, và trả về kết quả của kiểu đó. được quảng cáo thành một loại phổ biến.Với float f; long l;, có ít nhất ba ý nghĩa hợp lý cho một sự so sánh f==l [nó có thể đúc l nổi, nó có thể đúc lf-double, hoặc nó có thể đảm bảo rằng f là một số nguyên có thể được đúc để long, và rằng khi truyền nó bằng l]. Ngoài ra, trình biên dịch có thể đơn giản từ chối một so sánh hỗn hợp như vậy. Nếu tôi có bởi druthers, trình biên dịch sẽ được nối liền từ đúc các toán hạng cho các toán tử quan hệ ngoại trừ trong trường hợp chỉ có một ý nghĩa chính đáng. Yêu cầu những thứ được chuyển đổi hoàn toàn ở mọi nơi phải được so sánh trực tiếp là IMHO vô ích.