2011-09-21 8 views
31

Tôi đang bối rối về phân công trực tiếp và ternary có điều kiện khai thác được ưu tiên:ternary có điều kiện và toán tử gán ưu tiên

#include<stdio.h> 
int main(void) 
{ 
    int j, k; 

    j = k = 0; 
    (1 ? j : k) = 1; // first 
    printf("%d %d\n", j, k); 

    j = k = 0; 
    1 ? j : k = 1; // second 
    printf("%d %d\n", j, k); 
    return 0; 
} 

Tôi mong chờ đầu ra là:

1 0 
1 0 

Nhưng nó sẽ xảy ra là:

1 0 
0 0 

Plus Tôi nhận được cảnh báo này:

main.cpp: 20: cảnh báo: tuyên bố không có tác dụng

đó là khoảng dòng tôi nhận xét như thứ hai.

Vì toán tử gán trực tiếp có ít ưu tiên hơn toán tử điều kiện bậc ba, tôi đã mong các dòng được nhận xét là đầu tiên và thứ hai là tương đương. Nhưng không phải vậy.

Tôi cố gắng này với g ++ --version (Ubuntu 4.4.3-4ubuntu5) 4.4.3

+4

C++ là một điều kỳ diệu hay là một con thú? Sau khi dành một nửa chương trình cuộc sống của tôi với nó, tôi vẫn có thể bị bắt không biết ý nghĩa của những biểu thức đơn giản như thế này. Tôi phải nhìn vào tiêu chuẩn này. – Suma

Trả lời

18

Nhà điều hành được ưu tiên trong thư mục C/C++ ngôn ngữ không được định nghĩa bằng một bảng hoặc số, nhưng bằng ngữ pháp. Đây là ngữ pháp cho toán tử có điều kiện từ C++0x draft chương 5.16 Toán tử điều kiện [expr.cond]:

 
conditional-expression: 
    logical-or-expression 
    logical-or-expression ? expression : assignment-expression 

Bảng ưu tiên như this one Do đó đúng khi bạn sử dụng phân ở phía bên trái của doublecolon, nhưng không phải khi sử dụng trên bên phải. Lý do cho sự không đối xứng này tôi không có ý tưởng. Nó có thể là một lý do lịch sử: trong C kết quả có điều kiện không phải là lvalue, do đó gán một cái gì đó cho nó không có ý nghĩa, và cho phép chuyển nhượng được chấp nhận mà không có dấu ngoặc đơn có vẻ thông minh tại thời điểm đó.

+1

Tại sao bảng được nối kết (nhóm đó?: Và = cùng nhau) không chính xác ở bên phải dấu hai chấm? – foxcub

+2

@foxcub Phiên bản hiện tại của bảng là chính xác. Nhiệm vụ có cùng mức độ ưu tiên như điều kiện trong bảng và tính liên kết là phải sang trái, dẫn đến việc phân công được thực hiện đúng trước khi có điều kiện. Bảng [không chính xác tại thời điểm trả lời] (http://en.cppreference.com/mwiki/index.php?title=cpp/language/operator_precedence&oldid=5400), cho biết mức độ ưu tiên cao hơn cho điều kiện hơn là cho bài tập. – Suma

+0

Cú pháp C++ được định nghĩa là một ngữ pháp cú pháp, nhưng ngữ pháp đó được thiết kế để phù hợp với một bảng ưu tiên đơn giản. Bạn nói rằng bảng là "không chính xác khi được sử dụng ở phía bên trái của dấu hai chấm", nhưng do lý do đó ưu tiên cũng không chính xác khi được sử dụng ở bên trái của ']' trong một biểu thức như 'a [b + c]' . Yêu cầu của một bảng ưu tiên là * một biểu thức con nhìn thấy bởi hai toán tử mà chúng mong đợi một toán hạng được gán cho một toán tử có mức ưu tiên cao hơn (và các mối quan hệ bị phá vỡ bởi tính liên kết). * Yêu cầu này không bao giờ bị vi phạm. '?:' và '=' chỉ có cùng mức ưu tiên. – Museful

14

Dòng thứ hai là tương đương với:

1 ? (j) : (k = 1); 

Đó là giống như:

j; 

Tương tự như:

; 

Điều quan trọng là hai toán hạng của toán tử điều kiện bậc ba có thể là các biểu thức , do đó, toán tử ưu tiên không có liên quan ở đây. Đơn giản là toán hạng thứ hai là biểu thức gán k = 1.

+0

* nod * Vấn đề không liên quan gì đến ưu tiên của toán tử - đó là điều đó ?: là một toán tử ngắn mạch. –

+0

@KazDragon: Tôi đã làm rõ rằng - chìa khóa là các toán hạng là các biểu thức, do đó toán hạng thứ hai là toàn bộ biểu thức gán. (Tất cả các toán tử nhị phân logic chuẩn đều ngắn mạch, nhân tiện. Ngắn mạch đề cập đến việc đánh giá các câu lệnh có điều kiện chứ không phải là kết quả.) –

+6

Bạn đúng, nhưng câu hỏi là: tại sao nó tương đương với 1? (j): (k = 1); và không phải (1? j: k) = 1, khi điều kiện được cho là có mức độ ưu tiên cao hơn nhiệm vụ? – Suma

4

Trong trường hợp thứ hai,

1 ? j : k = 1; 

được đánh giá là:

(1) ? (j) : (k = 1); 

và từ một đánh giá để true, khái niệm để đánh giá j mà không làm gì.

9
(1 ? j : k) = 1; 

tương đương với,

if(true) j = 1; 
else k = 1; 

Và,

1 ? j : k = 1; 

tương đương với,

if(true) j; // warning: statement has no effect 
else k = 1; 
+1

+1 để nêu bật lý do cảnh báo xảy ra. – larsmoa