2013-06-18 11 views
11

Nie mogę znaleźć ostatecznej odpowiedzi na to: czy następujący kod ma niezdefiniowane zachowanie?Wiele przypisań złożonych w pojedynczej instrukcji: czy jest to niezdefiniowane zachowanie czy nie?

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

To jest * nie * duplikat. Tutaj wyrażenie to 'x + = (x + = 10)', które różni się od '(x + = 10) + = 10' - zachowanie tutaj jest niezdefiniowane tam, gdzie nie ma drugiego pytania (w C++ 11). – interjay

+0

Powyższy komentarz odnosi się do pytania [W którym wersjach standardu C++ "(i + = 10) + = 10" ma niezdefiniowane zachowanie?] (Http://stackoverflow.com/questions/10655290/in-whichwersions -of-the-c-standard-does-i-10-10-have-undefined-behaviou), który został wcześniej oznaczony jako duplikat. – interjay

+0

dlaczego tak naprawdę chcesz wiedzieć? – Alex

Odpowiedz

14

Zachowanie jest niezdefiniowane. Przyjrzyjmy się nieco prostsze wyrażenie:

x += (x+=1) 

w C++ 11, obliczanie wartości lewej x jest unsequenced stosunku do obliczania wartości wyrażenia (x+=1). Oznacza to, że obliczenie wartości x nie jest związane z przypisaniem do x (z powodu x+=1), a zatem zachowanie jest niezdefiniowane.

Powodem tego jest fakt, że obliczenia wartości dwóch boków operatora += nie są względem siebie wzajemnie odwzorowywane (ponieważ norma nie określa inaczej). I 1.9p15 stany:

Jeśli efektem ubocznym na skalarnym obiektu jest unsequenced w stosunku do każdej innej efektem ubocznym tego samego przedmiotu lub skalarne obliczenia wartości przy użyciu tej samej wartości skalarne obiektu, zachowanie jest niezdefiniowane.

W C++ 03 zachowanie jest niezdefiniowane, ponieważ x jest modyfikowane dwukrotnie bez interweniującego punktu sekwencji.

+2

Uwaga: jeśli 'x' był obiektem, z zdefiniowanym przez użytkownika' operatorem + = ', to byłby zdefiniowany ... –

+0

Przepraszamy za pierwsze zaniedbanie tego. Jak wyjaśniłeś w swoim komentarzu do pytania, oba wyrażenia są różne i rzeczywiście twoja odpowiedź jest całkowicie poprawna. +1 –

0

W przypadku standardowych ofert zobacz pozostałe odpowiedzi. Prawdopodobnie znajdzie się jedno z dwóch różnych zachowań w tym przypadku.

x += (x += 2); 

mogą być albo

x = 2 + 4 (= 6) 

Jeżeli wartość x po lewej stronie oceniano przed x+=2 lub

x = 4 + 4 (= 8) 

Jeżeli wartość x dla lewego operatora jest określana później.


-edit-

wiem, że nie będzie zbyt wielu fanów, więc jeśli powiem, że nie lubię tych „wszystko może się zdarzyć” roszczeń bardzo dużo. Prawdą jest, że każdy kompilator może zadeklarować się jako standardowy, niezależnie od tego, w jaki sposób instrukcja, którą tu omawiamy, jest obsługiwana w odniesieniu do wartości x. Niemniej jednak myślę, że nie oznacza to, że operator + = może skutkować błędnym wynikiem lub że paranty mogą być ignorowane. Niezdefiniowane zachowanie to nie to samo co niezdefiniowane zachowanie w każdym innym przypadku.

Jest zły na siebie na każdym oczekiwania dotyczące niezdefiniowanej zachowań, ale w powyższym przykładzie widzę powody, dla zaniedbując żadnego możliwego wyniku, ale 6 i 8.

Oprócz I rzeczywiście podejrzany x być 8 po ocenie z int x=2; x += (x += 2); dla większości znanych kompilatorów (clang, g ++, vc, icpc ...).

Należy powtórzyć, że nie należy polegać na takim zachowaniu, ale to nie znaczy, że jest całkowicie nieprzewidywalny.

+4

** Przynajmniej ** mogą wystąpić dwa zachowania. Zachowanie jest niezdefiniowane, więc wyliczanie możliwych zachowań jest nieskończonym zadaniem. –

+0

jest różnica między wykazaniem, że istnieją co najmniej dwa różne wyniki (pokazując przez sprzeczność) do wyliczenia. W przypadku 2 są to identyczne. – Alex

+1

Optymalizowanie kompilatorów może * zakładać *, że zachowanie twojego programu nie jest niezdefiniowane. Jeśli naruszysz to założenie, mogą wykonywać przekształcenia, które naruszają twoje * założenia. W każdym razie nie powinno to mieć znaczenia jak 'x + = (x + = 2);' zachowuje się; cokolwiek to ma znaczyć, jest wyraźniejszy sposób na wyrażenie tego. –

Powiązane problemy