Strona 1 z 1

C++: wynik działania +++

: 08 mar 2011, 11:55
autor: Enkidu
Dlaczego kompilator po kodzie:

Kod: Zaznacz cały

#include <iostream>
 
using namespace std;
 
int main() {
        int a = 0;
         int b = 4;
         int c = 9;
         a = b+++c;
         cout << a;
        return 0;
}
wyrzuca mi sumę, czyli w tym wypadku 13? Myślałem, że inkrementacja ma większy priorytet.

Odp: C++: wynik działania +++

: 08 mar 2011, 12:11
autor: VGT
Obstawiam, ze sumowanie wykonało się w ten sposób:

Kod: Zaznacz cały

a = b++ + c;
Post inkrementacja odbywa się po pobraniu wartosci b do sumowania.

Jeśli wpiszesz to tak:

Kod: Zaznacz cały

a = b + ++c;
Wtedy pre inkrementacja zwiększy c przed sumowaniem.

Odp: C++: wynik działania +++

: 08 mar 2011, 12:28
autor: Enkidu
Ha! ale tutaj w ogóle nie było inkremetacji, ani post ani pre, doszło do zwykłego zsumowania zmiennych.

Odp: C++: wynik działania +++

: 08 mar 2011, 12:32
autor: VGT
Enkidu pisze:Ha! ale tutaj w ogóle nie było inkremetacji[..]

A założymy się? ;)

Kod: Zaznacz cały

#include <iostream>

using namespace std;

int main() {
        int a = 0;
         int b = 4;
         int c = 9;
         a = b+++c;
         cout << a << endl << b;
        return 0;
}
Skompiluj i zobacz co się stało ze zmienną b.
Chyba nie do końca rozumiesz, jak działa inkrementacja i spodziewasz się jej gdzie indziej, niż wystąpiła.

PS. Ewentualnie może wprowadzasz siebie w błąd korzystając z działania +++?
Działanie inkrementacji, to ++, który można umieścić przed lub za zmienną, czyli ++a lub a++
To co ty stworzyłeś, to połączenie inkrementacji z sumowaniem, którego nawet nigdy nie robiłem i zaskoczyło mnie, że kompilator to wykonał.
Ale skoro wykonał to właśnie nie masz kontroli, czy jest to post inkrementacja zmiennej b, czy pre inkrementacja zmiennej c.

Odp: C++: wynik działania +++

: 08 mar 2011, 15:50
autor: Enkidu
Ja z tego nie korzystam, tylko miałem na teście.

A rzeczywiście, postinkrementacja zaszła :D Ale ja cały czas pytam o wynik działania - czemu najpierw sumuje a potem dopiero inkrementuje?

Kod: Zaznacz cały

a=++b+a;
W tym wypadku też wyjdzie 13.

Odp: C++: wynik działania +++

: 08 mar 2011, 17:19
autor: VGT
Enkidu pisze:

Kod: Zaznacz cały

a=++b+a;
W tym wypadku też wyjdzie 13.
Właśnie, że nie. Sprawdziłeś? Tutaj najpierw jest preinkrementacja, a potem sumowanie składników.
Enkidu pisze:Ale ja cały czas pytam o wynik działania - czemu najpierw sumuje a potem dopiero inkrementuje?
Bo w takiej kolejności działa postinkrementacja (w odróżnieniu od pre), a czym pisałem w pierwszym poście.
Wydaje mi się, że nie odróżniasz postinkrementacji od preinkrementacji uznając obydwie za to samo, a różnica jest zasadnicza.

Odp: C++: wynik działania +++

: 08 mar 2011, 21:08
autor: Enkidu
Uuu, racja - wyjdzie to samo. Wcześniej w pracy sprawdzałem, ale musiałem coś w kodzie namieszać.

W każdym razie zastanawiam się jak widzi to wyrażenie "a+++b" kompilator, postinkrementacje a, czy preinkrementację b? Z tego, co wyrzuca na wyjście, wynika, że widzi najpierw + przy b, a potem postinkrementację przy a.

Ale dlaczego nie widzi preinkrementacji przy b i potem sumy?

Odp: C++: wynik działania +++

: 08 mar 2011, 22:22
autor: VGT
Zapewne to kwestia podejścia kompilatora. Po prostu taka jest kolejność zapisana gdzieś w specyfikacji języka. Tak jak wcześniej pisałem, byłem zaskoczony, że coś takiego przechodzi. Dla pewności lepiej rozdzielać to spacjami. Sytuacja jest podobna, jak używanie wielu różnych operatorów bez grupowania w nawiasy. Jak wiesz, co robisz i znasz kolejność ich wykonywania, to można, ale bardzo łatwo o pomyłkę, którą potem ciężko namierzyć.

Nie zdziwiłbym się także, gdyby działanie tego "a+++b" mogło być różne w zależności od kompilatora. Na blogu Gynvael'a był ciekawy wpis o inkrementacji pokazujący, że takie sytuacje są możliwe: http://gynvael.coldwind.pl/?id=369

PS. Ogólnie to ja nie koduję w C / C++. Mogę mieć tutaj braki w wiedzy, więc jestem nieco zawiedziony, że jako jedyny odpowiadam w tym wątku. Przydałaby się jeszcze opinia kogoś, kto jest bardziej na bieżąco ;)

PS2. Z ciekawości przetestowałem w językach, których używam regularnie (PHP, Java) i w obydwu taki zapis jest możliwy i działa tak samo jak w C++.

Odp: C++: wynik działania +++

: 08 mar 2011, 23:25
autor: Enkidu
Myślę, że to wynika z faktu, że inkrementacja ma wyższy priorytet od znaku sumy ;) Ale zagadką pozostaje fakt jak w takim wypadku rozróżnia post i pre inkrementację kompilator.

Dodam, że w czystym C wynik jest ten sam.

Odp: C++: wynik działania +++

: 08 mar 2011, 23:47
autor: pax0r
C i C++ mialem juz jakis czas temu ale wydaje mi sie ze zapis a+++b to czy kompilator potraktuje to jako (a++)+b czy jako a+(++b) to jest undefined behaviour.

Odp: C++: wynik działania +++

: 09 mar 2011, 11:22
autor: Enkidu
Z tego co się orientuję undefined behaviour oznacza w praktyce jakiego kompilatora się używa ;)

Odp: C++: wynik działania +++

: 09 mar 2011, 12:26
autor: kklimonda
Ale to chyba nie jest niezdefiniowane, w tym przypadku interpretacja jest w miare prosta.
Kompilator rozbija b+++c na zmienną b, postinkrementację, sumę, zmienną b - w kolejności, w jakiej występują w kodzie bo parser czyta kod praktycznie znak po znaku.
Kiedy już ma wszystko wczytane to najpierw wykonuje b + c, a następnie b++, znów według zasad.

Odp: C++: wynik działania +++

: 10 mar 2011, 15:40
autor: Enkidu
Tzn. że ów parser czyta znaki od lewej do prawej, ale działania wykonuje od prawej do lewej i dlatego przypisanie wygląda tak jak na przykładzie.:
a=8+c
?

Odp: C++: wynik działania +++

: 10 mar 2011, 18:25
autor: maciejewski
zgadza sie.
jest dokladnie tak jak napisales.

Odp: C++: wynik działania +++

: 12 mar 2011, 12:43
autor: Kokosek
kklimonda pisze:Ale to chyba nie jest niezdefiniowane, w tym przypadku interpretacja jest w miare prosta.
Kompilator rozbija b+++c na zmienną b, postinkrementację, sumę, zmienną b - w kolejności, w jakiej występują w kodzie bo parser czyta kod praktycznie znak po znaku.
Kiedy już ma wszystko wczytane to najpierw wykonuje b + c, a następnie b++, znów według zasad.
Dokładnie. Parser jest zachłanny (greedy), czyli dopasowuje jak największe kawałki od razu.