2010-09-11 10 views
15

Dlaczego następujące kompilacji w C++?Wiele operacji przedwstępnych na zmiennej w C++ (C?)

int phew = 53; 
++++++++++phew ; 

Ten sam kod kończy się niepowodzeniem w C, dlaczego?

+0

Dodanie tagu C++ 0x dla zabawy. :) –

+1

Musi być standardowe pytanie, na które możemy odpowiedzieć w przypadku tego typu pytań. Wszystkie pytania (które otrzymujemy o tej porze roku od nowych studentów) mogą być szybko zamknięte i oznaczone jako przeczytane. –

Odpowiedz

13

To dlatego, że w C++ operatora preinkrementuj powraca się lvalue i wymaga jego operandu być lvalue.

++++++++++phew ; w interpretować jako ++(++(++(++(++phew))))

Jednak kod wywołuje Undefined Behaviour ponieważ staramy się zmodyfikować wartość phew więcej niż raz pomiędzy dwoma sequence points.

W C operator preinkrementuj powraca się rvalue i wymaga jego operandu być lvalue. Twój kod nie zostanie skompilowany w trybie C.

+2

@Prasoon: Nie przejmuj się, zgaduję, jestem ciekawa, co przeczytałeś; "próbujesz zmodyfikować wartość uśpienia więcej niż raz między dwoma punktami sekwencji". Czy możesz podać adnotację do tej części normy, abym mógł przeczytać więcej na ten temat? –

+3

@Merlyn Morgan-Graham: Przeczytaj ten artykuł Steve Summit: http://c-faq.com/expr/seqpoints.html. –

+0

'Komentarz" Ta specyfikacja musi być przestrzegana tylko wtedy, gdy istnieje więcej niż jeden dostęp między sekwencjami punktów lub dla obiektów zadeklarowanych przy użyciu klasy pamięci masowej. W przypadku dewelopera występuje modyfikacja . Dopóki implementacja przyniesie oczekiwany rezultat, może robić to, co lubi. –

27

Uwaga: dwa raporty o usterkach DR#637 i DR#222 są ważne, aby zrozumieć uzasadnienie zachowania poniżej.


Dla wyjaśnienia, w C++ 0x istnieją value computations i side effects. Efektem ubocznym na przykład jest przydział, a obliczenie wartości określa, do czego odnosi się l-wartość lub odczytuje wartość z l-wartości. Zauważ, że C++ 0x nie ma już punktów sekwencyjnych, a te rzeczy są sformułowane w terminach "zsekwencjonowane przed"/"zsekwencjonowane po". I stwierdzono, że

Jeśli efektem ubocznym na skalarnym obiektu jest unsequenced w stosunku do każdej innej efektem ubocznym tego samego skalarnego obiektu lub obliczeń wartość używając wartość samego skalarnego obiektu, zachowanie jest niezdefiniowane.

++v odpowiada v += 1 co jest równoważne v = v + 1 (z wyjątkiem, że V jest analizowany tylko raz). To daje ++ (v = v + 1), który napiszę jako inc = inc + 1, gdzie inc odnosi się do wyniku lwartości v = v + 1.

W C++ 0x ++ ++v nie jest niezdefiniowanym zachowaniem, ponieważ dla a = b przypisanie jest sekwencjonowane po obliczeniu wartości b i a, ale przed obliczeniem wartości wyrażenia przypisania. Wynika z tego, że przypisanie w v = v + 1 jest sekwencjonowane przed obliczeniem wartości inc. A przypisanie w inc = inc + 1 jest sekwencjonowane po obliczeniu wartości inc. Ostatecznie oba przypisania zostaną zsekwencjonowane i nie ma niezdefiniowanych zachowań.

+3

Dobra odpowiedź. Podobnie 'int a = 4; ++ a = 5; 'nie wywoływałoby UB w C++ 0x, prawda? –

+0

@Prasoon tak. Ustawiłoby 'a' na 5. Podobnie' a = ++ a; 'nie będzie UB, ale' a = a ++; 'będzie UB. –

+0

@ Janhannes: Cool :-). Świat się zmienia. –