2011-11-11 30 views
5

Theo PC-lint, báo cáo kết quả sau đây sẽ không bao giờ có TRUE:Câu lệnh C/C++ if() này có được đánh giá là TRUE không?

if((variable & 0x02) == 1) 

Tôi đang sử dụng một trình biên dịch C cho các hệ thống nhúng có đánh giá nó để TRUE bất cứ khi nào các bit tương ứng trong variable được thiết lập. Tôi đoán trình biên dịch đang thực hiện so sánh TRUE/FALSE của cả hai bên của == thay vì so sánh các số kết quả. Nói cách khác, mỗi khi biểu thức (varable & 0x02) không phải là số không (ví dụ: TRUE), thì tuyên bố cũng sẽ là TRUE, vì giá trị 1 is also TRUE (không phải bằng không).

Tôi không biết liệu các tiêu chuẩn C/C++ có xác định rõ cách trình biên dịch hoạt động trong trường hợp này hay không. Có bất kỳ chuyên gia C/C++ nào ở đó có thể trả lời câu hỏi này dựa trên những tiêu chuẩn (ví dụ: C90, C99,, v.v.) không?

P.S .: Trong tuyên bố ở trên, "biến" là một ký tự chưa được ký.

+4

'loại variable' là gì? –

+2

Bạn có thể đặt tên cho trình biên dịch này không? Một người bạn của tôi tạo ra một bộ sưu tập các lỗi trình biên dịch lẻ. – blaze

+1

Có thể mã thực của bạn có ký hiệu kép (ví dụ: "var && 0x02") không? Điều đó sẽ giải thích trình biên dịch đánh giá nó là đúng. – tinman

Trả lời

11

PC-lint là đúng. Giả sử var là biến số nguyên, biểu thức var & 0x02 có thể đánh giá thành hai giá trị: 02. Nó sẽ không bao giờ bằng 1, đó là những gì tuyên bố if đang thử nghiệm.

Để mở rộng về điều này, toán tử bình đẳng đang được áp dụng cho hai giá trị số nguyên. Điều quan trọng là liệu cả hai toán hạng đều đánh giá cùng một số, không cho dù cả hai đều đồng thời "đúng" hay "sai".

Để kiểm tra xem bit 1 được thiết lập, người ta có thể sử dụng:

if (variable & 0x02) { 
    ... 
} 

Cho rằng trình biên dịch của bạn cư xử theo cách bạn nói có, nó rõ ràng là không tuân thủ. Tuy nhiên, nó gần như chắc chắn sẽ xử lý chính xác if (variable & 0x02). Đề xuất của tôi là sửa mã để nó không bị ngắt quãng nếu bạn thay đổi trình biên dịch.

Cuối cùng, tình huống sẽ khác nếu: (1) mã là C++ chứ không phải C; và (2) variable là thể hiện của một lớp; và (3) lớp quá tải các toán tử được đề cập. Trong trường hợp đó, hành vi là xuống đến những gì các nhà khai thác quá tải thực sự làm.

+0

Điều này là do '0x02' chỉ có một bit được đặt trong mẫu bit của nó. –

+4

Đây không phải là trường hợp trong C++ do sự hiện diện của các toán tử quá tải. – bdonlan

+2

Lý tưởng nhất là bạn nên luôn sử dụng mẫu 'if ((variable & CONST) == CONST)' nếu bạn muốn kiểm tra xem tất cả các bit trong một mặt nạ đã cho có được đặt hay không. – tylerl

6

Trong C++, điều này có thể đánh giá thành giá trị thực nếu (và chỉ khi) variable là một thể hiện của một lớp có quá tải operator& không tuân theo bitwise AND ngữ nghĩa thông thường.

Trong C, điều kiện này sẽ luôn là sai. §6.5.10 định nghĩa ngữ nghĩa của các phép toán AND điều hành, và nó khá đơn giản và cho điểm:

  4. Kết quả của & điều hành nhị phân là phép toán AND giữa toán hạng (có nghĩa là, mỗi bit trong kết quả được đặt nếu và chỉ khi mỗi bit tương ứng trong toán hạng được chuyển đổi là bộ).

Rõ ràng là kết quả không được là 1, vì 1 bit không được đặt trong giá trị được chuyển đổi của toán hạng bên phải (cụ thể là, 0x02).

Đương nhiên, nếu hành vi không xác định đã được gọi tại một số điểm trong quá khứ của chương trình (hoặc tại thời gian biên dịch!), Thì mọi thứ đều có thể xảy ra. Tuy nhiên, ngăn chặn khả năng này, trình biên dịch của bạn không tuân thủ. Đó là để nói, bị hỏng. Điều này, thật không may, là cực kỳ phổ biến trên các trình biên dịch nhúng lẻ. Nếu bạn may mắn, bạn thậm chí có thể báo cáo lỗi và sửa lỗi.

4

Tôi không nghĩ tiêu chuẩn xác định bất kỳ điều gì về vấn đề rất cụ thể và bất thường này. Như đã nói bởi aix, tuyên bố rằng không bao giờ có thể đúng bởi vì (ở dạng nhị phân):

XXXX XXXX -> variable 
0000 0010 -> 0x02 
--------- AND 
0000 00X0 -> result 

(đơn giản hóa đến 8-bit loại)

Vì vậy, kết quả duy nhất của bạn có thể 0000 0010 (đó là 2) hoặc 0000 0000 (là 0).

+1

Cảm ơn bạn đã trình bày trực quan :) – AntonioCS

0

Về cơ bản, lint là ngay tại đây. Ít nhất là trên bất kỳ nền tảng nào tôi biết, điều kiện sẽ mang lại giá trị sai. Nhìn vào biểu diễn bit của các số: x & 2 (0010) sẽ luôn bằng 0 hoặc 2 (0010) và do đó khác với 1 (0001) đối với bất kỳ số nguyên nào x.

1

Đối với C, câu trả lời là không.

Các C standard nói về & (6.5.10):

Kết quả của & điều hành nhị phân là phép toán AND giữa toán hạng (có nghĩa là, mỗi bit trong kết quả được thiết lập khi và chỉ nếu mỗi bit tương ứng trong toán hạng được chuyển đổi là bộ).

Vì trong 2 chỉ bit 1 được đặt, giá trị của biểu thức chỉ có thể đặt bit 1. Không được có giá trị nào khác hơn 2 và 0. Không 2 hoặc 0 có thể so sánh bằng 1.

Biểu diễn bit của các số nguyên được xác định trong 6.2.6.2 (đối với các giá trị không âm theo cách thông thường).

0

Chúng ta hãy xem xét giá trị nhị phân của 2

02 = 0010 (say a 4 bit number) 

và giá trị nhị phân của 1 là

01 = 0001 

Bit significat nhất của 2 luôn là zero đó là các bit nhất còn lại là 0 SO
Hoạt động & (và) với 0 không bao giờ cho phép 1 do đó chúng tôi có thể nói rằng nó không bao giờ có thể bằng 1

 0 0 => 0 
     0 1 => 0 
     1 1 => 1 

Lưu ý: & chỉ ra chút khôn ngoan và hoạt động

2 - 0010 
    3 - 0011 
     0010 

Vì vậy, đầu ra với xx & 2 sẽ là 0 hoặc 2.

Các vấn đề liên quan