Bạn đang so sánh số unsigned int
với số signed char
. Các ngữ nghĩa của loại so sánh này phản trực giác: hầu hết các phép toán nhị phân liên quan đến các toán hạng signed
và unsigned
được thực hiện trên các toán hạng chưa ký, sau khi chuyển đổi giá trị đã ký thành unsigned (nếu cả hai toán hạng có cùng kích thước sau khi quảng bá). Dưới đây là các bước:
- Giá trị
signed char
được đề bạt lên một int
với cùng giá trị -23
.
- so sánh sẽ được thực hiện trên
int
và unsigned int
, loại thông thường là unsigned int
như được xác định trong tiêu chuẩn C.
int
được chuyển đổi thành unsigned int
với giá trị UINT_MAX - 23
, một số rất lớn.
- So sánh được thực hiện trên các giá trị
unsigned int
: 23
là giá trị nhỏ hơn, so sánh sẽ được tính là sai.
- Chi nhánh
else
được đánh giá, no
được in.
Để làm cho vấn đề tồi tệ hơn, nếu c
đã được định nghĩa là một long
, kết quả sẽ phụ thuộc vào việc long
và int
có cùng kích thước hay không. Trên Windows, nó sẽ in no
, trong khi trên Linux 64 bit, nó sẽ in yes
.
Không bao giờ trộn các giá trị đã ký và chưa ký trong so sánh. Bật cảnh báo trình biên dịch để ngăn chặn loại lỗi này (-Wall
hoặc -Weverything
). Bạn cũng có thể làm cho tất cả các cảnh báo này gây tử vong với -Werror
để tránh hoàn toàn loại mã bị lỗi này.
Đối với một tài liệu tham khảo đầy đủ, đọc phần sau của C chuẩn (C11) thuộc 6.3 Chuyển đổi:
- chương trình khuyến mãi nguyên được giải thích trong 6.3.1.1 Boolean, ký tự, và số nguyên .
- chuyển đổi toán hạng được mô tả chi tiết trong 6.3.1.8 Chuyển đổi số học thông thường.
Bạn có thể tải dự thảo mới nhất của tiêu chuẩn C11 từ trang web của nhóm công tác: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
đọc về [hai của bổ sung] (https://en.wikipedia.org/wiki/Two%27s_complement). và về [chuyển đổi ngầm trong C] (http: //en.cppreference.com/w/c/language/conversion) (đặc biệt là về [các phép chuyển đổi số học] (http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions)). –
Nguồn kinh điển là [C standard] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) (đó là bản nháp N1570). Xem 6.3.1.1 cho các quảng cáo * số nguyên * (chuyển đổi giá trị 'char char' thành' int') và 6.3.1.8 cho * chuyển đổi số học thông thường * (chuyển đổi cả hai toán hạng thành kiểu chung, 'unsigned int' , trước khi thực hiện so sánh). –