2013-06-18 16 views
11

Tôi không thể tìm thấy câu trả lời cuối cùng cho điều này: mã sau có hành vi không xác định?Nhiều phép gán phức hợp trong một câu lệnh duy nhất: nó có phải là Hành vi không xác định hay không?

int x = 2; 
x+=x+=x+=2.5; 
+0

Đây là * không * trùng lặp. Ở đây biểu thức là 'x + = (x + = 10)', khác với '(x + = 10) + = 10' - hành vi ở đây là không xác định nơi câu hỏi khác không phải (trong C++ 11). – interjay

+0

Nhận xét trên của tôi đề cập đến câu hỏi [Trong đó các phiên bản của tiêu chuẩn C++ có “(i + = 10) + = 10” có hành vi không xác định?] (Http://stackoverflow.com/questions/10655290/in-which-versions -of-the-c-tiêu chuẩn-không-i-10-10-có-undefined-behaviou) mà trước đó được đánh dấu là trùng lặp. – interjay

+0

tại sao bạn thực sự muốn biết? – Alex

Trả lời

14

Hành vi không xác định. Chúng ta hãy nhìn vào biểu hiện hơi đơn giản:

x += (x+=1) 

Trong C++ 11, việc tính toán giá trị của x trái là unsequenced liên quan đến việc tính toán giá trị của biểu thức (x+=1). Điều này có nghĩa là tính toán giá trị của x không được xác định liên quan đến việc gán cho x (do x+=1) và do đó hành vi không xác định.

Lý do cho việc này là tính toán giá trị của hai bên của toán tử += không được liên quan đến nhau (như tiêu chuẩn không chỉ định khác). Và 1.9p15 tiểu bang:

Nếu tác dụng phụ trên đối tượng vô hướng không bị ảnh hưởng liên quan đến một tác dụng phụ khác trên cùng một đối tượng vô hướng, hành vi không xác định.

Trong C++ 03 hành vi không xác định vì x được sửa đổi hai lần mà không có điểm trình tự xen kẽ.

+2

Lưu ý: nếu 'x' là một đối tượng, với một toán tử' do người dùng định nghĩa + = ', thì nó sẽ được xác định ... –

+0

Xin lỗi vì đã downvoting đầu tiên này. Như bạn đã giải thích trong nhận xét của mình về câu hỏi, hai biểu thức khác nhau và quả thực câu trả lời của bạn là hoàn toàn chính xác. +1 –

0

Đối với báo giá chuẩn, hãy xem các câu trả lời khác. Nó có khả năng tìm thấy một trong hai hành vi khác nhau trong trường hợp này.

x += (x += 2); 

hoặc Có thể

x = 2 + 4 (= 6) 

nếu giá trị của x trên bên trái được đánh giá trước khi x+=2 hoặc

x = 4 + 4 (= 8) 

nếu giá trị của x cho các nhà điều hành trái được xác định sau đó.


-edit-

Tôi biết tôi không sẽ nhận được rất nhiều người hâm mộ trên SO nếu tôi nói tôi không thích những "bất cứ điều gì có thể xảy ra" tuyên bố rất nhiều. Đúng là bất kỳ trình biên dịch nào cũng có thể tự khai báo tuân thủ chuẩn bất kể câu lệnh mà chúng ta thảo luận ở đây được xử lý như thế nào đối với giá trị của x. Tuy nhiên, tôi nghĩ điều đó không có nghĩa là toán tử + = có thể dẫn đến kết quả sai hoặc các dấu ngoặc đơn có thể bị bỏ qua. Hành vi không xác định không giống như hành vi không xác định trong bất kỳ trường hợp nào khác.

Nó là xấu để sao lưu trên bất kỳ kỳ vọng về hành vi không xác định nhưng trong ví dụ trên tôi thấy lý do chính đáng cho bỏ qua bất kỳ kết quả tốt nhưng 6 và 8.

Bên cạnh đó tôi thực sự nghi ngờ x là 8 sau khi thẩm định của int x=2; x += (x += 2); đối với hầu hết các trình biên dịch đã được thiết lập (clang, g ++, vc, icpc ...).

Cần nói lại rằng bạn không nên dựa vào hành vi như vậy nhưng điều đó không có nghĩa là nó hoàn toàn không thể đoán trước được.

+4

** Ít nhất ** hai hành vi có thể xảy ra ở đây. Hành vi là không xác định, vì vậy liệt kê các hành vi có thể là một nhiệm vụ bất tận. –

+0

có sự khác biệt giữa việc hiển thị rằng có ít nhất hai kết quả khác nhau (hiển thị theo mâu thuẫn) để liệt kê. Đối với trường hợp 2, chúng giống hệt nhau. – Alex

+1

Trình biên dịch tối ưu hóa được phép * giả sử * rằng hành vi của chương trình của bạn không được xác định. Nếu bạn vi phạm giả định đó, họ có thể thực hiện các phép biến đổi vi phạm * giả định của bạn *. Trong mọi trường hợp, nó không thực sự quan trọng như thế nào 'x + = (x + = 2);' cư xử; bất cứ điều gì nó có nghĩa là, có một cách rõ ràng hơn để thể hiện nó. –

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