Toán tử số học nhị phân sẽ thực hiện usual arithmetic conversions trên toán hạng của chúng để mang chúng đến một kiểu chung.
Trong trường hợp của i1
, i3
và i5
loại phổ biến sẽ unsigned int và do đó kết quả sẽ còn được unsigned int. Số chưa ký sẽ được bọc qua số học modulo và do đó trừ đi một giá trị chưa ký lớn hơn một chút sẽ dẫn đến một số gần với int tối đa không dấu mà không thể được đại diện bởi một int.
Vì vậy, trong trường hợp i1
, chúng tôi kết thúc bằng chuyển đổi được triển khai do giá trị không thể được biểu diễn. Trong trường hợp của i3
chia cho 2
đưa giá trị chưa ký trở lại vào phạm vi của int và vì vậy chúng tôi kết thúc với giá trị int đã ký lớn sau khi chuyển đổi.
Các phần có liên quan tạo thành tiêu chuẩn dự thảo C++ như sau. Mục 5.7
[expr.add]:
Các nhà khai thác phụ gia + và - nhóm từ trái sang phải. Chuyển đổi số học thông thường được thực hiện cho toán hạng của số học hoặc kiểu liệt kê.
Quá trình chuyển đổi số học thông thường được bảo hiểm trong phần 5
và nó nói:
Nhiều nhà khai thác nhị phân mà mong đợi toán hạng số học hoặc liệt kê loại nguyên nhân chuyển đổi và mang lại loại kết quả theo một cách tương tự. Mục đích là để mang lại một loại phổ biến, đó cũng là loại kết quả. mô hình này được gọi là chuyển đổi số học thông thường, được định nghĩa như sau:
[...]
- Ngược lại, nếu các toán hạng có kiểu dữ liệu integer unsigned có xếp hạng lớn hơn hoặc bằng với xếp hạng của loại toán hạng khác, toán hạng có loại số nguyên đã ký sẽ được chuyển thành loại toán hạng với loại số nguyên không dấu.
và cho việc chuyển đổi từ một giá trị mà không thể được đại diện cho một loại ký, phần 4.7
[conv.integral]:
Nếu loại đích được ký kết, giá trị không thay đổi nếu nó có thể được thể hiện trong loại đích (và chiều rộng trường bit); nếu không, giá trị được xác định thực hiện.
và cho số nguyên unsigned tuân theo modulo số học phần 3.9.1
[basic.fundamental]:
số nguyên Unsigned phải tuân theo pháp luật của số học modulo 2n trong đó n là số bit trong giá trị đại diện cho kích thước cụ thể đó của số nguyên.48
Nguồn
2015-09-09 12:07:30
_Tuy nhiên, gán giá trị đó cho i1 là hành vi không xác định_ Bạn có chắc chắn về điều đó không? Tôi dạy rằng chuyển đổi từ int unsigned để ký int cũng được xác định cho tất cả các giá trị của unsigned int. – rozina
Không có tràn số nguyên đã ký ở đây. Có chuyển đổi. Xem [conv.integral] (http://eel.is/c++draft/conv.integral). – Sebivor
@rozina: Huh, tôi chưa từng thấy chuyển đổi đó hoạt động khác theo khía cạnh này. Cố định – Hurkyl