2010-09-03 13 views
17

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?

+0

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

+0

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'. –

+0

Ah, przepraszam. Źle cię przeczytałem. Przepraszam. – Stephen

Odpowiedz

23

gwarantuje się, że kolejnych porównań (c == coś w tym przykładzie) wykorzystuje wartość ustawioną przez canInitWithSomeValue (& C)?

Tak. Ponieważ nie jest sequence point

Między oceną lewej i prawej argumentów Spośród && (logiczne AND), || (logiczne OR) oraz operatorów przecinkami. Na przykład w wyrażeniu *p++ != 0 && *q++ != 0 wszystkie efekty uboczne podekspresji * p ++! = 0 są kończone przed każdą próbą uzyskania dostępu do q.


Punkt sekwencja definiuje dowolny punkt w realizacji programu komputerowego jest przy której jest gwarantowane, że wszystkie skutki uboczne poprzednich ewaluacji zostaną przeprowadzone, a żadne skutki uboczne kolejnych ocenach jeszcze zostały przeprowadzone .

+0

świetna odpowiedź, dzięki! –

5

Tak. Ponieważ zarówno operator &&, jak i || są również czymś, co nazywa się punktami sekwencji. Te ostatnie określają, kiedy skutki uboczne poprzedniej operacji powinny być zakończone, a następne nie powinny się rozpocząć.

1

Ocena w warstwie kompilacji if jest ściśle od lewej do prawej. Jedyną okolicznością, w której drugi test w twoim przypadku byłby zoptymalizowany, jest to, czy kompilator może ustalić z 100% pewnością, że pierwszy jest identycznie równy false.

Powiązane problemy