2012-01-28 78 views
29

int:Sự khác biệt thực sự giữa "int" và "unsigned int"

32-bit int kiểu dữ liệu có thể giữ giá trị số nguyên trong khoảng -2147483648 đến 2,147,483,647. Bạn cũng có thể tham khảo loại dữ liệu này dưới dạng int đã ký hoặc đã ký.

unsigned int:

32-bit unsigned int data loại có thể giữ giá trị số nguyên trong khoảng từ 0 đến 4294967295. Bạn cũng có thể chỉ loại dữ liệu này đơn giản là chưa được ký.

Ok, nhưng, trong thực tế:

int x = 0xFFFFFFFF; 
unsigned int y = 0xFFFFFFFF; 
printf("%d, %d, %u, %u", x, y, x, y); 
// -1, -1, 4294967295, 4294967295 

có sự khác biệt, O.o. Tôi hơi bối rối.

+1

Bạn cần suy nghĩ về biểu diễn _binary_ của cả 'int' và' int unsigned'. – Oded

+1

Lý do thực sự có thể xảy ra là C là ngôn ngữ * yếu * * đã nhập *. Nhưng 'unsigned int' và' int' thực sự khác. – cha0site

+1

http://stackoverflow.com/questions/247873/signed-versus-unsigned-integers –

Trả lời

34

Hehe. Bạn có một diễn viên tiềm ẩn ở đây, bởi vì bạn đang yêu cầu printf loại mong đợi.

Hãy thử điều này trên cho kích thước thay vì:

unsigned int x = 0xFFFFFFFF; 
int y = 0xFFFFFFFF; 

if (x < 0) 
    printf("one\n"); 
else 
    printf("two\n"); 
if (y < 0) 
    printf("three\n"); 
else 
    printf("four\n"); 
21

Có, vì trong trường hợp của bạn, họ sử dụng the same representation.

Mẫu bit 0xFFFFFFFF xảy ra giống như -1 khi được hiểu là số nguyên được ký 32b và là 4294967295 khi được hiểu là số nguyên không dấu 32b.

Giống như char c = 65. Nếu bạn diễn giải nó như một số nguyên đã ký, thì đó là 65. Nếu bạn diễn giải nó như một ký tự, nó là a.


Khi R và pmg chỉ ra, về mặt kỹ thuật, hành vi không xác định để chuyển đối số không khớp với định dạng thông số. Vì vậy, chương trình có thể làm bất cứ điều gì (từ in ấn các giá trị ngẫu nhiên để đâm, để in "quyền" điều, vv).

Những điểm chuẩn nó ra trong 7.19.6.1-9

Nếu chuyển đổi Speci fi cation là không hợp lệ, hành vi được unde fi Ned. Nếu bất kỳ đối số nào không đúng loại cho chuyển đổi tương ứng đặc điểm, hành vi không được xác định.

+4

Lý do thực sự là anh ta đang sử dụng% u để in cả hai. –

+3

Lý do thực sự là anh ta ** viện dẫn hành vi không xác định ** bằng cách chuyển một chuỗi định dạng không khớp với 'printf'. Tôi gần như muốn downvote tất cả các câu trả lời được bỏ qua này và chỉ ra những thứ không liên quan về đại diện ... –

+1

@R .. Đúng vậy, không khớp định dạng và các đối số là hành vi không xác định. Cảm thấy tự do để downvote, tôi sẽ không nhớ :-) – cnicutar

1

loại chỉ cho bạn biết mẫu bit được cho là đại diện. các bit chỉ là những gì bạn tạo ra. các trình tự tương tự có thể được diễn giải theo nhiều cách khác nhau.

1

Chức năng printfdiễn giải giá trị mà bạn chuyển nó theo trình định dạng định dạng ở vị trí phù hợp. Nếu bạn thông báo printf rằng bạn vượt qua một số int, nhưng vượt qua unsigned thay vào đó, printf sẽ diễn giải lại cái kia làm bản in khác và in kết quả mà bạn thấy.

3

Các đại diện bên trong của intunsigned int là như nhau.

Do đó, khi bạn chuyển cùng một chuỗi định dạng đến printf, nó sẽ được in giống nhau.

Tuy nhiên, có sự khác biệt khi bạn so sánh chúng. xem xét:

int x = 0x7FFFFFFF; 
int y = 0xFFFFFFFF; 
x < y // false 
x > y // true 
(unsigned int) x < (unsigned int y) // true 
(unsigned int) x > (unsigned int y) // false 

Điều này có thể cũng là một caveat, bởi vì khi so sánh chữ ký và số nguyên unsigned một trong số họ sẽ được ngầm đúc để phù hợp với các loại.

7

Sự cố là bạn đã gọi Undefined Behaviour.


Khi bạn gọi UB mọi thứ đều có thể xảy ra.

Bài tập được chấp thuận; có một chuyển đổi ngầm trong dòng đầu tiên

int x = 0xFFFFFFFF; 
unsigned int y = 0xFFFFFFFF; 

Tuy nhiên, các cuộc gọi đến printf, không phải là ok

printf("%d, %d, %u, %u", x, y, x, y); 

Đó là UB đến không phù hợp các % specifier và loại của các đối số.
Trong trường hợp của bạn, bạn chỉ định 2 int s và 2 unsigned int s theo thứ tự này bằng cách cung cấp 1 int, 1 unsigned int, 1 int, và 1 unsigned int.


Đừng làm UB!

+0

-1, sai. Đây không phải là hành vi không xác định. Kiểm tra C99 phần 6.5.2.2 đoạn 6. – cha0site

+1

@ cha0site: Tôi đặc biệt nói rằng các bài tập là ok: * phần 6.5.2.2 đoạn 6 * không thực sự áp dụng cho câu trả lời của tôi. UB đang trong cuộc gọi 'printf': kiểm tra [7.19.6.1] (http://port70.net/~nsz/c/c99/n1256.html#7.19.6):" Nếu bất kỳ đối số nào không đúng loại cho đặc tả chuyển đổi tương ứng, hành vi không xác định ". Cũng lưu ý 'printf' là một hàm lấy một số biến số của các đối số và các chuyển đổi theo nguyên mẫu là không thể. – pmg

+0

C99 [6.5.2.2] (http://port70.net/~nsz/c/c99/n1256.html#6.5.2.2) được ưu tiên hơn. Có khuyến mãi số nguyên. Tôi có thể đã bị đánh cắp - có thể là đoạn 5. – cha0site

1

Anh ấy hỏi về sự khác biệt thực sự. Khi bạn đang nói về hành vi không xác định bạn đang ở cấp độ bảo lãnh được cung cấp bởi đặc tả ngôn ngữ - nó xa thực tế. Để hiểu được sự khác biệt thực xin vui lòng kiểm tra đoạn này (tất nhiên đây là UB nhưng nó hoàn toàn xác định trên trình biên dịch yêu thích của bạn):

#include <stdio.h> 

int main() 
{ 
    int i1 = ~0; 
    int i2 = i1 >> 1; 
    unsigned u1 = ~0; 
    unsigned u2 = u1 >> 1; 
    printf("int   : %X -> %X\n", i1, i2); 
    printf("unsigned int: %X -> %X\n", u1, u2); 
} 
9

Không có sự khác biệt giữa hai trong cách thức chúng được lưu trữ trong bộ nhớ và thanh ghi, không có phiên bản đăng ký int đã ký và chưa ký, không có thông tin đã ký được lưu trữ với int, sự khác biệt chỉ có liên quan khi bạn thực hiện các phép toán, có phiên bản đã ký và chưa ký của các toán học được tích hợp vào CPU và trình biên dịch sử dụng phiên bản nào.

+0

Câu trả lời này là câu trả lời đơn giản nhất –

1

Cái này khá thẳng về phía trước. Biểu diễn nhị phân là khóa được đề cập nhưng không bao giờ được hiển thị. Chưa được ký trong HEX nếu 0XFFFFFFF = mã máy = 1111 1111 1111 1111 1111 1111 1111 1111 = 4,294,967,295 biểu thị tích cực của một số. Đó là tất cả tốt và dandy nhưng chúng ta cần một cách để đại diện cho số âm. Vì vậy, bộ não quyết định bổ sung twos. Điều này có nghĩa là, trong ngắn hạn, họ lấy số lớn nhất bên trái và quyết định rằng khi nó là 1 (tiếp theo là tất cả cho đến khi bạn đạt tới bit quan trọng nhất bên trái), số sẽ âm nếu 0 . Bây giờ, hãy xem điều gì xảy ra 0000 0000 0000 0000 0000 0000 0000 0011 = 3. Bây giờ chúng ta tiếp tục thêm vào con số này 0111 1111 1111 1111 1111 1111 1111 1111 = 2.147.483.645 số dương cao nhất với một int ký kết. Hãy thêm 1 (ở đây bạn có thể muốn tìm kiếm phần bổ sung nhị phân) chúng ta phải thực hiện theo cách thông qua. 1111 1111 1111 1111 1111 1111 1111 1110 = -1 Vì vậy, tôi đoán trong ngắn hạn chúng ta có thể nói rằng sự khác biệt là một trong những phép cho số âm kia không, mà là do các bit hoặc trái nhất chút dấu hoặc bit quan trọng nhất.

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