Đây là lỗi của Visual Studio, nhưng hãy bắt đầu bằng các khía cạnh không phải là lỗi.
Mục 5, Chú giải 9 của then applicable C++ standard đầu tiên thảo luận về những việc cần làm nếu các toán hạng là độ rộng chút khác nhau, trước khi tiếp tục phải làm gì nếu họ đều giống nhau nhưng khác nhau về dấu:
.. Nếu không, nếu toán hạng có loại số nguyên không dấu có xếp hạng lớn hơn hoặc bằng cấp bậc của loại toán hạng khác, toán hạng với loại số nguyên đã ký phải được chuyển thành loại toán hạng với số nguyên không dấu kiểu.
Đây là nơi chúng tôi biết rằng so sánh phải hoạt động với số học chưa ký. Bây giờ chúng ta cần tìm hiểu ý nghĩa của giá trị -10.
phần 4.6 cho chúng ta biết:
Nếu loại đích là unsigned, giá trị kết quả là ít nhất unsigned integer đồng dư với số nguyên nguồn (modulo 2 n trong đó n là số bit được sử dụng để đại diện cho loại unsigned). [Lưu ý: Trong đại diện bổ sung của hai, chuyển đổi này là khái niệm và không có thay đổi về mẫu bit (nếu không có cắt ngắn).- lưu ý cuối cùng] 3 Nếu loại đích được ký, giá trị không thay đổi nếu nó có thể được thể hiện trong loại đích (và chiều rộng bit); nếu không, giá trị được thực hiện.
Như bạn có thể thấy, một giá trị cụ khá cao (4294967286, hoặc 0xFFFFFFF6, giả sử unsigned int
là một số 32-bit) được so sánh với 10, và do đó đảm bảo tiêu chuẩn mà printf
thực sự không bao giờ gọi.
Bây giờ bạn có thể tin rằng không có quy tắc nào trong tiêu chuẩn yêu cầu chẩn đoán trong trường hợp này, do đó trình biên dịch không có vấn đề gì. (Trên thực tế, một số người viết -1
với ý định sản xuất một tất cả-những mẫu bit. Những người khác sử dụng int
cho mảng lặp lại, mà kết quả trong ký/so sánh unsigned giữa size_t
và int
. Xấu xí, nhưng được bảo đảm để biên dịch.)
Bây giờ Visual Studio ban hành một số cảnh báo "tự nguyện".
Điều này dẫn đến một cảnh báo đã được thiết lập mặc định (mức 3):
int a = -10;
unsigned int b = 10;
if(a < b) // C4018
{
printf("Error in line above: this will not be printed\n");
}
Sau đây đòi hỏi /W4
để có được một cảnh báo. Lưu ý rằng cảnh báo đã được phân loại lại. Nó đã thay đổi từ cảnh báo C4018 thành cảnh báo C4245. Điều này rõ ràng là do thiết kế. Một lỗi logic phá vỡ một so sánh gần như luôn luôn là ít nguy hiểm hơn so với một trong đó xuất hiện để làm việc với các so sánh tích cực tích cực nhưng phá vỡ với những người tiêu cực tích cực.
const int a = -10;
unsigned int b = 10;
if(a < b) // C4245
{
printf("Error in line above: this will not be printed\n");
}
Nhưng trường hợp của bạn là chưa khác nhau:
int a = -10;
const unsigned int b = 10;
if(a < b) // no warning
{
printf("Error in line above: this will not be printed\n");
}
Và không có cảnh báo nào. (Vâng, bạn nên thử lại với -Wall
nếu bạn muốn chắc chắn.) Đây là một lỗi. Microsoft says về nó:
Cảm ơn bạn đã gửi phản hồi này. Đây là trường hợp mà chúng tôi sẽ phát ra cảnh báo C4018. Rất tiếc, vấn đề cụ thể này là không phải là mức độ ưu tiên đủ cao để khắc phục trong bản phát hành tiếp theo cho các tài nguyên mà chúng tôi có sẵn.
Hết sức tò mò, tôi đã kiểm tra bằng Visual Studio 2012 SP1 và lỗi vẫn ở đó - không cảnh báo với -Wall
.
Nghe giống như lỗi trình biên dịch. Nó có thể được tối ưu hóa biến, vì vậy bạn chỉ có 'a <10'. – AlchemicalApples
@DBRalir: không, đợi đã, đúng rồi! một biến 'const' của kiểu số nguyên được khởi tạo với biểu thức hằng số biên dịch-thời gian ... nó _is_' a <10'. –
trên gcc 4.4 nó không hiển thị bất kỳ cảnh báo nào với const hoặc không có const –