Số nguyên đã ký trong C đại diện cho số. Nếu a
và b
là các biến của các kiểu số nguyên đã ký, tiêu chuẩn sẽ không bao giờ yêu cầu trình biên dịch biến biểu thức a+=b
lưu trữ thành a
bất cứ thứ gì ngoài tổng số học của các giá trị tương ứng của chúng. Để chắc chắn, nếu tổng số học không phù hợp a
, bộ xử lý có thể không thể đặt nó ở đó, nhưng tiêu chuẩn sẽ không yêu cầu trình biên dịch cắt bớt hoặc bọc giá trị, hoặc làm bất cứ điều gì khác cho vấn đề đó nếu giá trị vượt quá các giới hạn cho các loại của họ. Lưu ý rằng mặc dù tiêu chuẩn không yêu cầu nó, nhưng việc triển khai C được phép bẫy các số tràn số học với các giá trị đã ký.
Các số nguyên không được gán trong C hoạt động như các vòng đại số trừu tượng của các số nguyên tương ứng với một số lũy thừa, ngoại trừ trong các trường hợp liên quan đến chuyển đổi hoặc hoạt động với các loại lớn hơn. Chuyển đổi một số nguyên có kích thước bất kỳ thành loại không dấu 32 bit sẽ mang lại thành viên tương ứng với những thứ phù hợp với mod số nguyên đó là 4.294.967.296. Lý do trừ 3 từ 2 mang lại 4.294.967.295 là vì thêm một cái gì đó phù hợp với 3 vào một cái gì đó phù hợp với 4.294.967.295 sẽ mang lại một cái gì đó phù hợp với 2.
Các loại vòng đại số trừu tượng thường là những thứ tiện dụng cần có; Thật không may, C sử dụng chữ ký làm yếu tố quyết định cho việc một loại có nên hoạt động như một chiếc nhẫn hay không. Tệ hơn, các giá trị không dấu được coi là số thay vì thành viên vòng khi được chuyển đổi thành loại lớn hơn và giá trị không dấu nhỏ hơn int
được chuyển đổi thành số khi bất kỳ số học nào được thực hiện theo chúng. Nếu v
là một uint32_t
mà bằng 4,294,967,294
, sau đó v*=v;
nên thực hiện v=4
. Thật không may, nếu int
là 64 bit, thì không biết v*=v;
phải làm gì.
Với tiêu chuẩn như hiện tại, tôi sẽ đề nghị sử dụng các loại không dấu trong các tình huống trong đó người ta muốn hành vi liên quan đến các vòng đại số và các loại được ký khi muốn đại diện cho các số. Thật không may khi C đã vẽ ra sự khác biệt theo cách nó đã làm, nhưng chúng là những gì chúng là.