2011-11-24 18 views
5

Niedawno irytować brzmienie C++ urywek:Expression zamówienie ocena

#include <cstdio> 

int lol(int *k){ 
    *k +=5; 
    return *k; 
} 

int main(int argc, const char *argv[]){ 
    int k = 0; 
    int w = k + lol(&k); 
    printf("%d\n", w); 
    return 0; 
} 

Spójrz na linii:

int w = k + lol(&k); 

Do tej pory myślałem, że to wyrażenie będzie obliczane od lewej do prawej : bierz aktualną wartość k (która przed wywołaniem funkcji lol wynosi 0), a następnie dodaj ją do wyniku funkcji lol. Ale kompilator udowadnia mi, że się mylę, wartość w wynosi 10. Nawet jeśli zamienić się miejscami, aby to

int w = lol(&k) + k; 

wynik byłby jeszcze 10. Co robię źle?

Tomka

+0

nic, '+' jest ostatnim op – volody

Odpowiedz

3

To dlatego, że parametry wyrażenia są nie podano do oceny w określonej kolejności.

Najpierw kompilator może wykonać jeden z parametrów: k lub lol(&k). W tym wyrażeniu nie ma punktów sekwencji. Oznacza to, że efekty uboczne parametrów mogą być wykonywane w dowolnej kolejności.

Krótko mówiąc, nie określono, czy kod drukuje 5 czy 10. Oba są prawidłowymi wyjściami.

Wyjątkiem jest zwarcie w wyrażeniach logicznych, ponieważ && i || są punktami sekwencji. (zobacz komentarze)

+0

'&&', '||' i '?:', Które pojawiają się w wyrażeniach, są punktami sekwencji. –

+0

@MarceloCantos: Dzięki za tę odrobinę informacji. Nie byłem pewien na temat dokładnych semanteków języka, które różniły wyrażenia boolowskie. Wyjaśniłem moją odpowiedź. – Mysticial

+0

Zauważ, że tylko wbudowane '&&' i '||' (a także ',') są punktami sekwencji. Jeśli są przeciążone, stają się funkcjami dwuargumentowymi, a kolejność wartości argumentów funkcji jest nieokreślona. –

2

Plus jest z definicji przemienny, więc kolejność w twoim przykładzie jest całkowicie zdefiniowana przez implementację.

Mysticial ma rację, wspominając o punktach sekwencji. Powołując Wikipedia article (nie mają standard C++ pod ręką):

Punkt sekwencja w programowaniu bezwzględnej definiuje dowolny punkt w realizacji danego programu komputerowego, w którym gwarantuje się, że wszystkie boczne skutki poprzednich ewaluacji zostaną wykonano i nie zostały jeszcze wykonane żadne działania po kolejnych ocenach. Są one często wymienione w odniesieniu do C i C++, ponieważ wynik niektórych wyrażeń może zależeć od kolejności ich podekspresji. Dodanie jednego lub więcej punktów sekwencji to jedna metoda zapewniająca spójny wynik, ponieważ ogranicza to możliwe oceny.

Artykuł zawiera również listę punktów sekwencji w C++.

+0

"_Twój przykład jest całkowicie zdefiniowany w implementacji." Nie, nie jest. Żadna implementacja, którą znam nie określa, co się dzieje. – curiousguy

+0

@cualnyguy: Być może, nie wyraziłem się jasno. Czy powinienem powiedzieć "specyficzne dla implementacji" lub "specyficzne dla kompilatora"? –

+0

lub "zależny od implementacji" lub "nieokreślony". – curiousguy

3

Ten kod daje 5 lub 10 w zależności od wyboru wartości oderu funkcji w stosunku do tej z lewej strony +.

Jego zachowanie to nie niezdefiniowane, ponieważ wywołanie funkcji jest otoczone dwoma punktami sekwencji.