2010-10-12 59 views
6
int main() { 
    int i = -3, j = 2, k = 0, m; 
    m = ++i || ++j && ++k; 
    printf("%d %d %d %d\n", i, j, k, m); 
    return 0; 
} 

tôi nghĩ rằng & & được ưu tiên hơn || theo logic này ++j nên thực thi, nhưng nó không bao giờ thực hiện và chương trình sẽ xuất ra -2 2 0 1. Chuyện gì đang xảy ra ở đây? Các bước trung gian là gì?Đánh giá biểu thức C

Trả lời

14

&& không có mức độ ưu tiên cao hơn ||, có nghĩa là ++i || ++j && ++k phân tích cú pháp là ++i || (++j && ++k).

Tuy nhiên điều này không thay đổi thực tế là RHS của || chỉ thực hiện nếu LHS trả về 0.

Ưu tiên không ảnh hưởng đến thứ tự đánh giá.

+1

Bạn có nghĩa là LHS. – SLaks

+1

@SLaks: Vâng, tôi có. Đã chỉnh sửa. – sepp2k

4

C++ sử dụng đánh giá lười biếng cho các nhà khai thác hợp lý.
Nếu bạn viết a || ba là đúng, b sẽ không bao giờ đánh giá, vì kết quả sẽ đúng ngay cả khi b là sai.
Tương tự, a && b sẽ không đánh giá b nếu a là sai.

++i đánh giá thành giá trị trung thực, không có biểu thức nào khác được đánh giá.

+0

Và 'm' là 1 vì ...? – sje397

+0

C++ sử dụng đánh giá lười biếng ... một chút quá rộng một tuyên bố. Ví dụ 0 & x luôn là 0 nhưng x vẫn được đánh giá. Sự lười biếng này, hoặc, chính xác hơn, đánh giá ngắn mạch chỉ đề cập đến các toán tử tích hợp && và || (và theo một nghĩa nào đó? :) –

+0

@ sje397: Bởi vì sự thật (kết quả của mệnh đề '||') là '1'. – SLaks

1

& & và || sử dụng đánh giá ngắn mạch, tức là trong biểu thức & & b a được đánh giá trước tiên, nếu sai thì toàn bộ biểu thức là sai và b không được đánh giá. Trong || b nếu a là true thì b không được đánh giá. Lưu ý rằng nếu bạn quá tải & & hoặc || quy tắc ngắn mạch sẽ không còn áp dụng nữa. HTH

7

Ưu tiên không có ảnh hưởng đến thứ tự đánh giá (trừ khi cần thiết - một số biểu thức phụ có thể cần phải được đánh giá trước những người khác do ưu tiên). Ví dụ, trong biểu thức đơn giản:

a() + b() + c() * d() 

mặc dù nhân có ưu tiên hơn Thêm vào đó, trình biên dịch là miễn phí để thực hiện các cuộc gọi đến các chức năng trong bất kỳ thứ tự nó thích, và có thể gọi a() hoặc b() trước hoặc sau nó thực hiện phép nhân. Rõ ràng, nó phải đánh giá c()d() trước khi nó thực hiện phép nhân. Nếu các hàm này có các tác dụng phụ (như sửa đổi và sử dụng các biến toàn cầu), thứ tự đánh giá không xác định có thể dẫn đến kết quả không mong muốn.

Tuy nhiên, đối với một số nhà khai thác, tiêu chuẩn này quy định một thứ tự đánh giá nghiêm ngặt. Điều này để nói về nhà điều hành hoặc hợp lý ||:

Không giống như bitwise | toán tử || nhà điều hành đảm bảo đánh giá từ trái sang phải; có một điểm chuỗi sau khi đánh giá toán hạng đầu tiên. Nếu toán hạng đầu tiên so sánh không bằng với 0, toán hạng thứ hai không được đánh giá.

Vì vậy, không chỉ || cung cấp đảm bảo đặt hàng, nó cũng đảm bảo rằng trong các điều kiện nhất định, toán hạng thứ hai sẽ không được đánh giá.

(nó cũng nói điều gì đó tương tự cho && - ngoại trừ trường hợp đó toán hạng thứ 2 không được đánh giá nếu lần đầu tiên đánh giá 0. Nhưng trong ví dụ của bạn, || xuất hiện trước).

Các toán tử khác cung cấp một số đảm bảo đặt hàng bao gồm toán tử dấu phẩy và cuộc gọi hàm (đảm bảo rằng đối số đã được đánh giá, nhưng không phải thứ tự các đối số đã được đánh giá).

+1

Giải thích hay. Tôi muốn nói thêm rằng có một lý do chính đáng để đánh giá ngắn mạch - nó làm cho điều kiện dễ dàng hơn nhiều để viết. Ví dụ: if (i baz! = MAGIC_NUMBER).Bạn biết phần đầu tiên (aka bảo vệ) được đánh giá đầu tiên, vì vậy bạn sẽ không đọc bên ngoài mảng hoặc dereference NULL. Nếu không có lệnh bảo đảm, bạn sẽ phải lồng hai lệnh if. Một số ngôn ngữ khác, thứ tự không được bảo đảm, vì vậy bạn thấy lồng nhau nếu các câu lệnh được sử dụng như một người bảo vệ mọi lúc. –

1

C không short-circuiting các biểu thức logic, vì vậy đánh giá của ++i là đủ để hình dung ra rằng m nên là sự thật.

0

Were bạn một cách tình cờ thực sự muốn gõ:

m = ++i | ++j & ++k; 

mà kết quả đầu ra -2 3 1 -1

+0

không, FWIW tôi biết sự khác biệt giữa các toán tử bitwise và các toán tử khác. – shreyasva

+0

Tôi nghĩ rằng bạn đã làm, vì vậy đã không cố gắng để được presumptuous :) Tôi đã dạy kèm một người nào đó ngày khác, những người đã có họ bối rối. –

0

m = ++ i || ++ j & & ++ k;

Kể từ && có độ ưu tiên cao hơn || để biểu thức được hiểu là ++i || (++j && ++k)

|| là ngắn mạch và toán hạng tay nên phải || điều hành không được đánh giá vì ++i trả về một giá trị không bằng không.

1
  1. Các || lực lượng khai thác trái sang phải thẩm định, vì vậy các biểu hiện ++i là hoàn toàn đánh giá đầu tiên, với một kết quả của -2.
  2. Toán tử || buộc một điểm chuỗi, do đó tác dụng phụ được áp dụng và i hiện bằng -2.
  3. Kết quả của biểu thức ++i không phải là 0, vì vậy biểu thức ++j && ++k không được đánh giá.
  4. Vì LHS không khác, kết quả của toàn bộ biểu thức ++i || ++j && ++k1 (đúng), được gán cho m.

Chỉ cần lặp lại những gì người khác đã nói, ưu tiên và thứ tự đánh giá không giống nhau.

+0

+1 - câu trả lời duy nhất cho đến nay trả lời * tất cả * của câu hỏi. – sje397

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