2012-08-27 36 views
7

Điều gì đang xảy ra ở đây?Ưu tiên của toán tử dấu phẩy bên trong toán tử điều kiện trong C++ là gì?

#include <iostream> 
using namespace std; 

int main(){ 

    int x=0,y=0; 
    true? ++x, ++y : --x, --y; 
    cout << "x: " << x << endl; 
    cout << "y: " << y << endl; //why does y=0 here? 

    x=0,y=0; 
    false ? ++x, ++y : --x, --y; 
    cout << "x: " << x << endl; 
    cout << "y: " << y << endl; 
} 

x: 1 
y: 0 

x: -1 
y: -1 

Trường hợp thứ hai có vẻ ổn. Tôi hy vọng cả x và y sẽ tăng lên 1 trong trường hợp đầu tiên nhưng chỉ tăng các toán hạng bên trái.

+0

Vui lòng cung cấp mã thực sự biên dịch - nếu không tôi không thể bị làm phiền để giúp bạn –

+0

'++ y' xảy ra, nhưng sau đó' --y'. 'đúng không? ++ x, ++ y: --x, --y' được phân tách thành '(true? ++ x, ++ y: --x), --y' – oldrinb

+0

@AdrianCornish Mã này biên dịch; bạn đã thử à? – chrisaycock

Trả lời

17

Người đầu tiên là tương đương với:

(true ? (++x, ++y) : (--x)), --y; 

Điều thứ hai là tương đương với:

(false ? (++x, ++y) : (--x)), --y; 

Do đó --y luôn thực thi. Trong dòng đầu tiên, các gia số được thực hiện trước tiên nên x = 1, y = 0 được mong đợi. Trong dòng thứ hai, việc giảm số x được thực hiện trước tiên nên x = -1, y = -1 được mong đợi.


Như đã đề cập trong một chú thích (để câu trả lời khác) bởi Barmar:

Và trong trường hợp bất cứ ai đang tự hỏi tại sao những dấu phẩy giữa ++x++y không có tác dụng tương tự, đó là vì (true? ++x) sẽ không hợp lệ chút nào. Vì vậy, trình biên dịch tiếp tục quét cho đến khi nó tìm thấy :, nhưng ngoài ra nó dừng lại khi nó đạt đến toán tử ưu tiên thấp hơn [(, trong ví dụ này) hoặc kết thúc câu lệnh].

+1

Để nêu rõ đoạn cuối cùng của bạn chính xác hơn: ưu tiên (và tính tương đối) của các toán tử chỉ ảnh hưởng đến sự ràng buộc của toán hạng ở bên trái và bên phải của toán tử chứ không ảnh hưởng đến toán hạng ở giữa. Tất nhiên, toán tử ternary là toán tử duy nhất có toán hạng trung ở vị trí đầu tiên. Nhưng dọc theo những dòng này, ta có thể xem cặp ngoặc đơn là toán tử đơn nhất (nhận dạng) có toán hạng đơn ở giữa (giữa ký hiệu toán tử), điều này giải thích tại sao nhóm nó đạt được không bị ảnh hưởng bởi bất kỳ quy tắc ưu tiên nào. –

0

Đọc tiêu chuẩn

§5.18 Comma điều hành [expr.comma]

¶1 Các nhóm hành dấu phẩy từ trái sang phải.

expression: 
assignment-expression 
expression , assignment-expression 

Một cặp biểu thức được phân tách bằng dấu phẩy được đánh giá từ trái sang phải; biểu thức bên trái là biểu thức hủy bỏ giá trị (Điều 5). Mọi tính toán giá trị và tác dụng phụ liên kết với biểu thức bên trái được sắp xếp theo trình tự trước mỗi lần tính toán giá trị và tác dụng phụ liên kết với biểu thức đúng. Loại và giá trị của kết quả là loại và giá trị của toán hạng bên phải; kết quả là cùng một loại giá trị làm toán hạng bên phải của nó và là trường bit nếu toán hạng bên phải của nó là glvalue và bit-field.

¶2 Trong ngữ cảnh mà dấu phẩy có ý nghĩa đặc biệt, [Ví dụ: trong danh sách đối số cho hàm (5.2.2) và danh sách khởi tạo (8.5) —ví dụ: toán tử dấu phẩy như được mô tả trong Điều 5 chỉ có thể xuất hiện trong dấu ngoặc đơn. [Ví dụ:

f(a, (t=3, t+2), c); 

có ba đối số, thứ hai trong số đó có giá trị 5. -end dụ]

+0

Cảm ơn bạn đã chỉnh sửa gọn gàng Jon –

+0

Cảm ơn bạn. thật? (++ x, ++ y): (--x, --y); đã sửa. Bài học: luôn sử dụng dấu ngoặc đơn trong đó ý định không tầm thường. – hhbilly

+2

@ user1626720 - chưa kể "không lạm dụng toán tử bậc ba". Mã được đề cập phải được viết nếu ... khác, vì giá trị của toán tử bậc ba bị loại bỏ. –

4

Các y là zero vì dấu phẩy có the lowest precedence among all C++ operators.Vì ưu tiên của nó thấp hơn mức ưu tiên của toán tử điều kiện bậc ba, toán tử điều kiện được phân tích cú pháp là true? ++x, ++y : --xfalse? ++x, ++y : --x. Trong cả hai trường hợp, câu lệnh --y được thực hiện vô điều kiện.

EDIT Dấu phẩy đầu tiên là khác nhau vì trình biên dịch đã tìm thấy một ?, vì vậy bây giờ nó cần một : để hoàn thành "khi true" biểu hiện của điều kiện. Đó là lý do tại sao cả hai ++x++y được lấy.

+3

Và trong trường hợp bất kỳ ai tự hỏi tại sao dấu phẩy giữa '++ x' và' ++ y' không có cùng tác dụng, đó là vì '(true? ++ x)' sẽ không hợp lệ. Vì vậy, nó tiếp tục quét cho đến khi nó tìm thấy ':', nhưng ngoài ra nó dừng lại khi nó đạt đến một toán tử ưu tiên thấp hơn. – Barmar

+1

Oh và không bao giờ làm 'if (x == 100.000)' học được rằng cách cứng ;-) –

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