2010-04-26 36 views
60

Tôi đã tò mò muốn biết điều gì sẽ xảy ra nếu tôi gán một giá trị âm cho một biến chưa ký.Điều gì sẽ xảy ra nếu tôi gán một giá trị âm cho biến chưa ký?

Mã sẽ trông hơi giống thế này.

unsigned int nVal = 0; 
nVal = -5; 

Nó không cho tôi bất kỳ lỗi trình biên dịch nào. Khi tôi chạy chương trình, nVal được gán một giá trị kỳ lạ! Có thể nào là giá trị bổ sung của một số 2 được gán cho nVal?

+1

linh cảm của tôi (đã không thể đến tìm thấy nó trong tiêu chuẩn được nêu ra) là hành vi là kỹ thuật không xác định. Hơn nữa, tôi nghi ngờ rằng bạn sẽ thấy những gì bạn mong đợi trên khá nhiều bất kỳ trình biên dịch bạn có thể tìm thấy. Vì vậy, trong khi bạn thường sẽ thấy hành vi đó, nó có lẽ không phải là một ý tưởng tốt để dựa vào nó. – sblom

+5

Nó không phải là không xác định (xem * §4.7/2 *), nhưng đại diện (ví dụ như bổ sung 2s) không được bắt buộc theo tiêu chuẩn. –

+0

@gf (et al bên dưới), tuyệt. Có vẻ như hành vi này, trên thực tế, được định nghĩa rõ ràng là những gì bạn mong đợi, @viswanathan. – sblom

Trả lời

50

cho câu trả lời chính thức - Phần 4.7 [conv.integral]

"Nếu loại đích là unsigned, giá trị kết quả là ít nhất số nguyên không dấu đồng dư với số nguyên nguồn (modulo 2^n trong đó n là số bit được sử dụng để biểu diễn loại không dấu) [Lưu ý: Trong biểu diễn bổ sung của hai, chuyển đổi này là khái niệm và không có thay đổi trong mẫu bit (nếu không có cắt ngắn) - hãy chú ý]

+27

* Số nguyên không dấu nhỏ nhất đồng dư với số nguyên nguồn * có nghĩa là gì? –

+6

@ DavidRodríguez-dribeas Ví dụ, 5 và 3 là "modulent mod 2" vì 5% 2 và 3% 2 đều là 1. – JoeQuery

4

Nó sẽ hiển thị dưới dạng số nguyên dương của giá trị của số nguyên không dấu tối đa - 4 (giá trị phụ thuộc vào kiến ​​trúc và trình biên dịch máy tính).

BTW
Bạn có thể kiểm tra điều này bằng cách viết một C đơn giản ++ "hello world" loại chương trình và xem cho chính mình

+0

Tôi đã viết và kiểm tra nó thats lý do tại sao tôi hỏi câu hỏi nhưng tôi didnt biết làm thế nào trình biên dịch đến lúc đó giá trị tích cực. Cảm ơn – ckv

1

Vâng, bạn đã đúng. Giá trị thực được chỉ định giống như tất cả các bit được đặt trừ thứ ba. -1 là tất cả các bit thiết lập (hex: 0xFFFFFFFF), -2 là tất cả các bit ngoại trừ đầu tiên và như vậy. Những gì bạn sẽ thấy có lẽ là giá trị hex 0xFFFFFFFB mà theo số thập phân tương ứng với 4294967291.

+3

Bit không có gì để làm với nó, đại diện số nguyên không được chỉ định. – GManNickG

+1

Câu trả lời của bạn là chính xác, nghiêm ngặt, đến mức mà tôi sẽ không bao giờ sử dụng trong lớp học. – Martin

+0

xem câu trả lời của tôi cho phần bổ sung 2 của -5. Tôi không nghĩ rằng bạn đã làm toán học của bạn một cách chính xác trên các giá trị nhị phân ở đây. – cynistersix

4

Bạn phải, số nguyên đã ký được lưu trữ trong dạng bổ sung của 2 và số nguyên không dấu được lưu trữ trong unsigned binary representation. C (và C++) không phân biệt giữa hai, vì vậy giá trị bạn kết thúc chỉ đơn giản là giá trị nhị phân không dấu của biểu diễn nhị phân bổ sung của 2.

+14

Nó có thể không được lưu trữ trong lời khen của 2. – GManNickG

+0

Điều gì có nghĩa là nếu một cái gì đó được "lưu trữ trong 2?" @GManNickG – JeremyF

+3

@JeremyF: Không phải "của 2", "lời khen của 2". Đó là một thuật ngữ có thể có của Google và là cách đại diện cho các số nguyên đã ký. – GManNickG

21

Nó sẽ chỉ định mẫu bit đại diện cho -5 (trong phần bổ sung 2) cho int không dấu. Đó sẽ là một giá trị lớn chưa ký. Đối với ints 32 bit này sẽ là 2^32-5 hoặc 4294967291

+1

Bit không có gì để làm với nó. – GManNickG

+9

@GMan: Câu trả lời trong câu trả lời của bạn chứa từ "bit" ... –

+0

@BenVoigt: Đủ công bằng, tôi có nghĩa là nó không liên quan gì đến cách bit được diễn giải. (Tức là, "bit" trong phần được trích dẫn chỉ là viết tắt của 'ceil (log_2 (x))'.) – GManNickG

1

Đây là những gì tôi đã chạy trên Objective-C iOS 4.3

unsigned long testValue = 0; 

NSLog(@"The value is: %lu", testValue); 
testValue -= 5; 
NSLog(@"The new value is: %lu", testValue); 

Output ra cửa sổ Console:

The value is: 0 
The new value is: 4294967291 

Giá trị mới trong Hex là 0xFFFFFFFB

Đó là sự bổ sung của 2 -5

Các vấn đề liên quan