Ok, jestem trochę Zawstydzony zadać to pytanie, ale ja po prostu chcesz mieć pewność ...Zwarcie oceny i skutki uboczne
Wiadomym jest, że C wykorzystuje krótkie oceny obwodu w wyrażeniach logicznych:
int c = 0;
if (c && func(c)) { /* whatever... */ }
W tym przykładzie func(c)
nie nazywa bo c
ocenia się 0
. Ale co powiesz na bardziej wyrafinowany przykład, w którym efekty uboczne porównania zmienią porównywalną zmienną w następnej kolejności? Tak:
int c; /* this is not even initialized... */
if (canInitWithSomeValue(&c) && c == SOMETHING) { /*...*/ }
Funkcja canInitWithSomeValue
powraca prawdziwa wartość i zmiany w danym wskaźnikiem w przypadku powodzenia. Czy jest zagwarantowane, że kolejne porównania (c == SOMETHING
w tym przykładzie) używają wartości ustawionej przez canInitWithSomeValue(&c)
?
Nie ważne jak ciężkie optymalizacje wykorzystuje kompilator?
Myślę, że możesz być mylące oceny zwarcia i optymalizacji kompilatora. W pierwszym przykładzie kompilator zoptymalizuje całą instrukcję 'if', ponieważ nigdy nie może jej uruchomić. Ocena zwarciowa oznaczałaby, że gdybyś miał "if (func1() i& func2()) {...}", a func1() byłby oceniany jako fałszywy ** w czasie wykonywania ** (tzn. Nie był definetycznie podczas kompilowania), to kod nie powinien sprawdzać 'func2()' - kompilator powinien utworzyć kod maszynowy taki, że jeśli 'func1()' ma wartość false, 'func2()' nie jest wywoływane. – Stephen
To 'int c = 0' było tam, aby wskazać, że' c' jest równe '0' w czasie porównania, zdaję sobie sprawę, że w takim przypadku kompilator zoptymalizowałby całe' if'. –
Ah, przepraszam. Źle cię przeczytałem. Przepraszam. – Stephen