2013-05-17 17 views
7

I'v một đoạn mã sau:là ưu tiên của các nhà điều hành bỏ qua trong 'nếu' điều kiện

void main() 
{ 
    int k, x, y, z; 
    printf("\nExperiment 1:"); 
    x = 0, y = 0, z = 0; 
    k = x++ || y++ && z++; 
    printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k); 
    printf("\nExperiment 2:"); 
    x = 1, y = 0, z = 0; 
    k = x++ || y++ && z++; 
    printf("\nx = %d, y = %d, z = %d and k = %d\n", x, y, z, k); 
} 

Sản lượng:

Thí nghiệm 1: x = 1, y = 1, z = 0 và k = 0

Thí nghiệm 2: x = 2, y = 0, z = 0 và k = 1

những gì tôi đã hiểu là: Đối với các biểu hiện đến mức khó tin, một trong hai bên trái hoặc bên phải của '||' phải không khác. Nó bắt đầu từ bên trái. Nếu trái không khác, nó không đánh giá thêm. Nếu nó bằng không, nó bắt đầu ở phía bên phải. Ở bên phải, chúng tôi có '& &'. Vì vậy, chúng tôi một lần nữa bắt đầu từ bên trái của & & và trong trường hợp nó bằng không, biểu thức không thể đúng và biểu thức không tiếp tục. Nếu không, nó sẽ đánh giá bên phải của '& &'

Giả định của tôi là toán tử & & có mức độ ưu tiên cao hơn. Vì vậy, cả hai đối số của nó nên đã được đánh giá và sau đó & & nên đã được áp dụng trên nó tiếp theo là đánh giá của cả hai đối số của ||.

Trình biên dịch có tự tối ưu hóa không? Tôi đã sử dụng Visual Studio TC tương tự với Tối ưu hóa bị vô hiệu hóa.

+5

Đây không phải là "nếu điều kiện", nhân tiện. Chúng đơn giản là các biểu thức, sử dụng các toán tử boolean và các toán tử tăng sau. – unwind

+3

Chỉ vì && có ưu tiên chặt chẽ hơn không có nghĩa là 'k = x ++ || (y ++ && z ++) 'sẽ thực hiện && trước ||. Điều này được gọi là ngắn mạch và rất nổi tiếng. Bạn thậm chí còn tự nhắc đến nó. Hãy tưởng tượng: 'k = x ++ || f (& y, & z) 'trong đó f() trả về' (* y) ++ && (* z) ++ '. Nó có chức năng tương đương với mã của bạn. – Matthias

+0

@Matthias: thực sự; '+ +' có ưu tiên cao hơn so với '&&'; chúng ta không mong đợi sự gia tăng sau khi xảy ra trước khi mọi thứ khác chỉ vì ưu tiên ... – geoffspear

Trả lời

9

Tôi nghĩ rằng đây được bao phủ trong C11 bởi §6.5.14 Logical OR operator (tôi nhấn mạnh)

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

4

Vì vậy, sự biểu hiện

k = x++ || y++ && z++; 

được hiểu như là (do precendence quy tắc):

k = x++ || (y++ && z++); 

Trong Thí nghiệm 1, ta có x = y = z = 0;.

Trong thử nghiệm 2, chúng tôi có x = 1, y = z = 0;.

Vì vậy, biểu thức bên tay phải dừng sau khi đánh giá y++, vì giá trị là 0 và do đó boolean và không thể trở thành sự thật.