Rozważmy następujący program w C:Czy określone jest zachowanie i = post_increment_i(), nieokreślone lub niezdefiniowane?
int i = 0;
int post_increment_i() { return i++; }
int main() {
i = post_increment_i();
return i;
}
W odniesieniu do 2011 wersji standardu C (znany jako C11), które z następujących alternatyw jest prawdziwe:
- C11 gwarantuje, że główne zwrotów 0.
- C11 gwarantuje, że główny zwrot wynosi 0 lub 1.
- Zachowanie tego programu jest niezdefiniowane zgodnie z C11.
Istotne fragmenty ze standardu C11:
5.1.2.3 Wykonywanie programu
Dostęp lotny obiekt, modyfikujące obiekt, modyfikując plik lub wywołanie funkcji że czy dowolna z tych operacji to wszystkie skutki uboczne, które są zmianami w stanie środowiska wykonawczego . Ocena ogólnego wyrażenia obejmuje zarówno obliczenia wartości , jak i inicjowanie efektów ubocznych. Obliczenie wartości dla wyrażenia o wartości l obejmuje określenie tożsamości wyznaczonego obiektu.
Sekwencjonowane wcześniej jest asymetryczną, przechodnią, parami relacji między ocenami wykonywane przez jeden wątek, który indukuje częściową kolejność wśród tych ocen. Przy dwóch dowolnych ocenach A i B, jeśli A jest zsekwencjonowane przed B, wykonanie A poprzedzi wykonanie B. (I odwrotnie, jeżeli A jest zsekwencjonowane przed B, to B jest zsekwencjonowane po A.) Jeśli A nie jest sekwencjonowany przed lub po B, następnie A i B są niesekwencjonowane. Oceny A i B są w sposób nieoznaczony sekwencjonowane, gdy A jest zsekwencjonowany przed lub po B, ale nie jest to określone. Obecność punktu sekwencji między oceną wyrażeń A i B oznacza, że każde obliczenie wartości i efekt uboczny związany z A jest sekwencjonowany przed każdym obliczeniem wartości i skutkiem ubocznym związanym z B. (Podsumowanie sekwencji punkty są podane w załączniku C.)
13) Wykonania niesekwencjonowanych ocen mogą się wzajemnie przeplatać. Oceny zsekwencjonalnie niezdefiniowane nie mogą być przeplatane, ale mogą być wykonywane w dowolnej kolejności.
6.5 Ekspresja
Wyrażenie to sekwencja operatorów i argumentów, które określa obliczenia wartości lub że wyznacza obiektu lub funkcji, lub która wytwarza efekty uboczne, lub że wykonuje kombinację powyższych. Obliczenia wartości operandów operatora są sekwencjonowane przed obliczeniem wartości wyniku operatora.
przypadku efektem ubocznym w skalarnej przedmiotu jest unsequenced względem albo innego efektu ubocznego tego samego obiektu skalarną lub obliczania wartości z wykorzystaniem wartości skalarne samego obiektu, zachowanie jest nieokreślona. Jeśli istnieje wiele dopuszczalnych uporządkowania podekspresji wyrażenia , zachowanie jest niezdefiniowane, jeśli taki niesekwencjonowany efekt strony występuje w dowolnym porządku. wzywa
6.5.2.2 Funkcja
Jest punkt sekwencja po ocenach desygnatora funkcję i rzeczywistych argumentów, ale jeszcze przed rozmową. Każda ocena w funkcji wywołującej (w tym inne wywołania funkcji), która nie jest inaczej sekwencjonowana w inny sposób przed lub po wykonaniu funkcji wywoływanej, jest w sposób nieokreślony sekwencjonowana w odniesieniu do wykonania wywoływanej funkcji.
94) Innymi słowy, wykonywanie funkcji nie "przeplata się" ze sobą.
6.5.2.4 Postfix inkrementacji i Dół operatorzy
Wynik postfixa ++ operator wartość argumentu. Jako efekt uboczny, wartość obiektu operandu jest zwiększana (to znaczy wartość 1 odpowiedniego typu jest dodawana do wartości ). [...] Obliczenie wartości wyniku jest sekwencjonowane przed skutkiem ubocznym aktualizacji wartości zapisanej operandu na . W odniesieniu do niefunkcjonalnie niezdefiniowanego wywołania funkcji działanie Postfiksu ++ jest pojedynczą oceną.
6.5.16 Zadania
zadanie operatora przechowuje wartości w przedmiotu wyznaczone przez lewy argument. [...] Efektem ubocznym aktualizacji zapisanej wartości lewego argumentu jest sekwencjonowany po obliczeniach wartości lewego i prawego argumentu operacji. Oceny operandów nie sąsekwencjonowane.
6,8 sprawozdanie i bloki
pełne ekspresji jest ekspresja nie jest część innego wyrazu lub z declarator. Każde z poniższych jest pełnym wyrażeniem: [...] wyrażenie w wyrażeniu; [...] (opcjonalne) wyrażenie w instrukcji return . Istnieje punkt sekwencji między oceną pełnego wyrażenia a oceną następnego pełnego wyrażenia, które ma zostać ocenione.
Trzy alternatywne powyżej odpowiadają trzech przypadkach, odpowiednio:
- Efekt stronie operatora przyrostek przyrost sekwencjonuje przed przypisaniem w głównym.
- Efekt uboczny operatora przyrostowego przyrostka jest sekwencjonowany przed lub po przypisaniu w main, a C11 nie określa, który. (Innymi słowy, oba efekty uboczne są sekwencyjnie zsekwencjonowane.)
- Oba efekty uboczne są niesekwencjonowane.
Wydaje się, że pierwsza alternatywa posiada, następującym łańcuchu rozumowania:
Rozważmy regułę Każdy oceny w funkcji wywołującej (w tym innych wywołań funkcji), który nie jest inaczej zsekwencjonowane przed lub po wykonaniu ciała wywoływanej funkcji jest w sposób nieokreślony zsekwencjonowany w odniesieniu do wykonania wywoływanej funkcji. w 6.5.2.2. Założenie A: Efektem ubocznym operatora przypisania w głównym jest taka "ocena". Założenie B: Wyrażenie "wykonanie wywoływanej funkcji" obejmuje zarówno obliczenie wartości przyrostowego operatora przyrostu, jak i efekt uboczny przyrostkowego operatora przyrostu. Z tych założeń i powyższej reguły wynika, że albo I) obliczenie wartości i efekt uboczny przyrostowego operatora przyrostu są zsekwencjonowane przed efektem ubocznym operatora przypisania w głównym, lub II) obliczeniu wartości i skutku ubocznym operatora przyrostowego przyrostu są sekwencjonowane po efektach ubocznych operatora przypisania w main.
Rozważmy regułę Efektem ubocznym aktualizacji zapisanej wartości lewego operandu jest zsekwencjonowany po obliczeniach wartość lewej i prawej argumentów. Ta reguła wyklucza przypadek I powyżej. Wynika z tego, że przypadek II zachodzi. QED
Ogólnie rzecz biorąc, wygląda to na dość mocną argumentację. Odpowiada również temu, co intuicyjnie rozważa najbardziej prawdopodobną alternatywę.
Jednakże opiera się na konkretnych interpretacjach terminów "ocena" i "wykonanie wezwanej funkcji" (Założenia A i B) i niezupełnie prostej linii rozumowania, więc chciałem ją tam przekazać zobacz, czy ludzie mają powody, by uważać, że ta interpretacja jest nieprawidłowa. Należy zwrócić uwagę, że przypis 94 jest równoważny z tą interpretacją tylko wtedy, gdy ma zastosowanie również w tym sensie, że osoba wywołująca nie przeplata się z uczestnikiem, co z kolei oznacza, że "przeplatanie" oznacza przeplatanie w znaczeniu "abab", ponieważ oczywiście osoba wywołująca przeplata się z the callee w słabszym sensie "aba". Ponadto alternatywy 2 i 3 wydają się wiarygodne w scenariuszu, w którym kompilator wprowadza funkcję, a następnie wykonuje te same rodzaje optymalizacji, które motywują, dlaczego wyrażenie ma niezdefiniowane zachowanie.
pas de probleme. – wildplasser