Jest niezdefiniowany, ponieważ modyfikuje x
dwukrotnie między punktami sekwencji. Standard mówi, że jest niezdefiniowany, dlatego jest niezdefiniowany.
Tyle wiem.
Ale dlaczego?
Rozumiem, że zabranianie tego pozwala kompilatorom na lepszą optymalizację. Mogło to mieć sens, gdy wynaleziono C, ale teraz wydaje się słabym argumentem.
Gdybyśmy dzisiaj wymyślili na nowo C, czy zrobilibyśmy to w ten sposób, czy można to zrobić lepiej?
A może jest głębszy problem, który utrudnia zdefiniowanie spójnych reguł dla takich wyrażeń, więc najlepiej ich zabronić?
Przypuśćmy, że dzisiaj wymyślimy C na nowo. Chciałbym zasugerować proste reguły dla wyrażeń takich jak x=x++
, które wydają mi się działać lepiej niż istniejące reguły.
Chciałbym poznać Twoją opinię na temat sugerowanych reguł w porównaniu do istniejących lub innych sugestii.
Sugerowane zasady:
- Między punktami sekwencji kolejność oceny jest nieokreślona.
- Efekty uboczne występują natychmiast.
Nie wiąże się to z niezdefiniowanym zachowaniem. Wyrażenia oceniają tę lub inną wartość, ale na pewno nie sformatują dysku twardego (o dziwo, nigdy nie widziałem implementacji, w której x=x++
formatuje dysk twardy).
Przykładowe wyrażenia
x=x++
- Dobrze zdefiniowany, nie zmienia sięx
.
Najpierwx
jest zwiększany (natychmiast pox++
ocenie), a następnie zapisywana jest jego stara wartośćx
.x++ + ++x
- Przyrostyx
dwukrotnie, ocenia na2*x+2
.
Chociaż każda ze stron może być oceniona jako pierwsza, wynikiem jest albox + (x+2)
(lewa strona pierwsza), albo(x+1) + (x+1)
(prawa strona pierwsza).x = x + (x=3)
- Nieokreślony,x
ustaw na jedenx+3
lub6
.
Jeśli prawa strona jest oceniana jako pierwsza, to jestx+3
. Możliwe jest również, żex=3
najpierw jest oceniane, więc tak jest3+3
. W obu przypadkachx=3
przypisanie następuje natychmiast pox=3
dokonaniu oceny, więc zapisana wartość jest zastępowana przez inne przypisanie.x+=(x=3)
- Dobrze zdefiniowane, ustawionex
na 6.
Można argumentować, że jest to tylko skrót dla powyższego wyrażenia.
Ale powiedziałbym, że+=
należy to wykonać pox=3
, a nie w dwóch częściach (przeczytajx
, oceńx=3
, dodaj i zapisz nową wartość).
Jaka jest zaleta?
Niektóre komentarze podniosły ten dobry punkt.
Z pewnością nie sądzę, aby wyrażenia takie jak x=x++
powinny być używane w normalnym kodzie.
Faktycznie, jestem o wiele bardziej rygorystyczne niż - Myślę, że tylko dobre wykorzystanie dla x++
jako x++;
samotnie.
Myślę jednak, że reguły językowe muszą być tak proste, jak to możliwe. W przeciwnym razie programiści po prostu ich nie rozumieją. reguła zabraniająca dwukrotnej zmiany zmiennej między punktami sekwencji jest z pewnością regułą, której większość programistów nie rozumie.
Bardzo podstawowa zasada jest następująca:
jeśli A jest ważne, a B jest ważne i są one połączone w prawidłowy sposób, wynik jest ważny.
x
jest prawidłową wartością L, x++
jest prawidłowym wyrażeniem i =
jest prawidłowym sposobem łączenia wartości L i wyrażenia, więc dlaczego x=x++
nie jest legalne?
Standard C stanowi tutaj wyjątek, a ten wyjątek komplikuje reguły. Możesz przeszukać stackoverflow.com i zobaczyć, jak bardzo ten wyjątek wprowadza ludzi w błąd.
Więc mówię - pozbyć się tego zamieszania.
=== Podsumowanie odpowiedzi ===
Dlaczego to robisz
Próbowałem wyjaśnić w powyższej sekcji - chcę, aby reguły C były proste.Potencjał do optymalizacji:
Odsuwa to trochę kompilatora, ale nie widziałem niczego, co przekonałoby mnie, że może być znaczące.
Nadal można przeprowadzić większość optymalizacji. Na przykłada=3;b=5;
można zmienić kolejność, nawet jeśli standard określa kolejność. Wyrażenia takie jaka=b[i++]
wciąż można zoptymalizować podobnie.Nie możesz zmienić istniejącego standardu.
Przyznaję, że nie mogę. Nigdy nie myślałem, że mogę iść naprzód i zmieniać standardy i kompilatory. Chciałem tylko pomyśleć, czy można było zrobić inaczej.
x
do samego siebie nie ma sensu , a jeśli chcesz zwiększyćx
, możesz po prostu powiedziećx++;
- nie trzeba tego przypisania. Powiedziałbym, że nie należy tego definiować tylko dlatego, że trudno byłoby sobie przypomnieć, co się stanie.