Sự khác biệt giữa int có dấu và không được ký là gì?
Sự khác biệt giữa int có dấu và không được ký là gì?
Câu trả lời:
Như bạn có thể biết, int
s được lưu trữ bên trong dưới dạng nhị phân. Thông thường, một int
chứa 32 bit, nhưng trong một số môi trường có thể chứa 16 hoặc 64 bit (hoặc thậm chí là một số khác, thường nhưng không nhất thiết phải là lũy thừa của hai).
Nhưng đối với ví dụ này, chúng ta hãy xem xét các số nguyên 4 bit. Nhỏ xíu, nhưng hữu ích cho mục đích minh họa.
Vì có bốn bit trong một số nguyên như vậy, nó có thể giả sử một trong 16 giá trị; 16 là hai đến lũy thừa thứ tư, hoặc 2 nhân 2 lần 2 nhân 2. Những giá trị đó là gì? Câu trả lời phụ thuộc vào việc số nguyên này là a signed int
hay an unsigned int
. Với an unsigned int
, giá trị không bao giờ âm; không có dấu hiệu liên quan đến giá trị. Dưới đây là 16 giá trị có thể có của một bốn bit unsigned int
:
bits value
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10
1011 11
1100 12
1101 13
1110 14
1111 15
... và Đây là 16 giá trị có thể có của một bốn bit signed int
:
bits value
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
Như bạn thấy, đối với signed int
s, bit quan trọng nhất là 1
nếu và chỉ khi số âm. Đó là lý do tại sao, đối với signed int
s, bit này được gọi là "bit dấu".
(unsigned)(-1)
được yêu cầu là giá trị có thể biểu diễn lớn nhất cho unsigned
(không phụ thuộc vào biểu diễn nhị phân), điều này đúng với phần bù của 2, chứ không phải các biểu diễn khác.
int
và unsigned int
là hai kiểu số nguyên riêng biệt. ( int
cũng có thể được gọi là signed int
, hoặc chỉ signed
; unsigned int
cũng có thể được gọi là unsigned
.)
Như tên ngụ ý, int
là một ký kiểu số nguyên, và unsigned int
là một unsigned kiểu số nguyên. Điều đó có nghĩa int
là có thể đại diện cho các giá trị âm và chỉ unsigned int
có thể đại diện cho các giá trị không âm.
Ngôn ngữ C đặt ra một số yêu cầu đối với phạm vi của các loại này. Phạm vi của int
phải có ít nhất -32767
.. +32767
, và phạm vi của unsigned int
phải có ít nhất 0
.. 65535
. Điều này ngụ ý rằng cả hai loại phải có ít nhất 16 bit. Chúng là 32 bit trên nhiều hệ thống, hoặc thậm chí 64 bit trên một số hệ thống. int
thường có thêm một giá trị âm do biểu diễn bổ sung của hai được sử dụng bởi hầu hết các hệ thống hiện đại.
Có lẽ sự khác biệt quan trọng nhất là hành vi của số học có dấu và không dấu. Đối với đã ký int
, tràn có hành vi không xác định. Đối với unsigned int
, không có tràn; chẳng hạn như bất kỳ thao tác nào mang lại giá trị nằm ngoài phạm vi của kiểu UINT_MAX + 1U == 0U
.
Bất kỳ kiểu số nguyên nào, có dấu hoặc không dấu, lập mô hình một dải con của tập hợp vô hạn các số nguyên toán học. Miễn là bạn đang làm việc với các giá trị trong phạm vi của một loại, mọi thứ đều hoạt động. Khi bạn tiếp cận giới hạn dưới hoặc giới hạn trên của một loại, bạn gặp phải sự gián đoạn và bạn có thể nhận được kết quả không mong muốn. Đối với các kiểu số nguyên có dấu, vấn đề chỉ xảy ra đối với các giá trị âm và dương rất lớn, vượt quá INT_MIN
và INT_MAX
. Đối với các kiểu số nguyên không dấu, vấn đề xảy ra đối với các giá trị dương rất lớn và bằng không . Đây có thể là một nguồn lỗi. Ví dụ, đây là một vòng lặp vô hạn:
for (unsigned int i = 10; i >= 0; i --) [
printf("%u\n", i);
}
vì i
là luôn luôn lớn hơn hoặc bằng số không; đó là bản chất của các loại không dấu. (Bên trong vòng lặp, khi nào i
bằng 0, hãy i--
đặt giá trị của nó thành UINT_MAX
.)
Đôi khi chúng ta biết trước rằng giá trị được lưu trữ trong một biến số nguyên nhất định sẽ luôn là số dương - chẳng hạn khi nó được sử dụng để chỉ đếm mọi thứ. Trong trường hợp này, chúng ta có thể khai báo biến là không có dấu, như trong unsigned int num student;
,. Với khai báo như vậy, phạm vi giá trị số nguyên được phép (đối với trình biên dịch 32 bit) sẽ chuyển từ phạm vi -2147483648 đến +2147483647 thành phạm vi 0 đến 4294967295. Do đó, việc khai báo một số nguyên là không dấu gần như tăng gấp đôi kích thước lớn nhất có thể giá trị mà nó có thể giữ.
Theo thuật ngữ của giáo dân, int không dấu là một số nguyên không thể âm và do đó có phạm vi giá trị dương cao hơn mà nó có thể giả định. Một int có dấu là một số nguyên có thể âm nhưng có phạm vi dương thấp hơn để đổi lấy nhiều giá trị âm hơn mà nó có thể giả định.
Trong thực tế, có hai điểm khác biệt:
cout
trong C ++ hoặc printf
C): đại diện nguyên chút unsigned được hiểu như là một số nguyên không âm bởi các chức năng in.mã này có thể xác định số nguyên bằng cách sử dụng tiêu chí sắp xếp:
char a = 0;
a--;
if (0 < a)
printf("unsigned");
else
printf("signed");