inkrementacja a cout
Ostatnio zmodyfikowano 2015-10-21 12:06
licsiu Temat założony przez niniejszego użytkownika |
inkrementacja a cout » 2015-10-19 13:38:01 Witam wszystkich - pierwszy raz : ) zastanawia mnie mechanizm wypisywania na ekran inkrementowanych wartości int'a:
przykład:
int y;
y=0; cout << y << y << endl; // 00
y=0; cout << ++y << y << endl; // 10
// dotąd było wszystko jasne... od teraz już nie wiem czemu wypusuje to co w kom:
y=0; cout << y++ << y << endl; // 01 (dlaczego nie 00, ew 10?)
y=0; cout << y << ++y << endl; // 11
y=0; cout << y << y++ << endl; //10 (a to juz przekracza zupełnie moje wyobrażenie..)
pozdrawiam będę wdzięczny za zainteresowanie. Piotrek |
|
michal11 |
» 2015-10-19 14:42:16 Operator << to nic innego jak funkcja, to samo jest z operatorem ++. Czyli jedna z twoich linijek wygląda tak: operator <<( operator <<( cout, y ), operator ++( y ) ); i w takim wypadku mógłbyś sobie pomyśleć, ze najpierw powinna wykonać się "lewa" funkcja a później prawa, prawda ? Niestety tak nie jest, standard nie definiuje w jakiej kolejności są wykonywane funkcje przekazywane jako argumenty funkcji. W podanym przykładzie może najpierw wykonać się operator ++( y ) a dopiero później operator <<( cout, y ) a równie dobrze na innym kompilatorze może być odwrotnie. Mam tylko nadzieje, że nic nie pokręciłem i pekfos mnie nie wyśmieje ;). |
|
Rashmistrz |
» 2015-10-20 23:38:16 @licsiu będę wdzięczny za zainteresowanie. |
Zwykle robię co w mojej mocy. :-_/ @michal11 Z tego co ja wiem to wyrażenie jest brane od lewej do prawej: Brany jest strumień (cout) i to co ma zostać wysłane do niego. Wykonywana jest operacja wstawienia do strumienia (skrócone o inne), a następnie jest zwracana referencja do otrzymanego strumienia. Następnie przechodzi do wykonania kolejnego "<<" i dzieje się tak, aż napotkany będzie średnik; Tak dla mnie wygląda działanie tego kodu... Dlatego nie potrafię się doszukać przyczyny takich wyników. Ach ten lukier składniowy... ____________________________________ #include <iostream> using std::cout; using std::endl;
int main() { char tab1[] = { '0', '\0' }; char & y = * tab1; cout <<( y++, tab1 ) << tab1 << endl; y = '0'; cout << tab1 <<( ++y, tab1 ) << endl; y = '0'; cout << tab1 <<( y++, tab1 ) << endl; char z = 'A'; z = 'A'; cout << z++ << z << endl; z = 'A'; cout << z << ++z << endl; z = 'A'; cout << z << z++ << endl; cout << '\n'; char tab2[] = { '0', '\0' }; char & a = * tab2; ((( cout <<( a++, tab2 ) ) << tab2 ) << endl ); a = '0'; ((( cout << tab2 ) <<( ++a, tab2 ) ) << endl ); a = '0'; ((( cout << tab2 ) <<( a++, tab2 ) ) << endl ); char b = 'A'; b = 'A'; ((( cout << b++ ) << b ) << endl ); b = 'A'; ((( cout << b ) << ++b ) << endl ); b = 'A'; ((( cout << b ) << b++ ) << endl ); cout << '\n'; char c = '0'; c = '0'; cout.put( c++ ).put( c ).put( '\n' ); c = '0'; cout.put( c ).put( ++c ).put( '\n' ); c = '0'; cout.put( c ).put( c++ ).put( '\n' ); cout << '\n'; }
Mam tego dość. Nie rozumiem tego. To całkowicie przechodzi moje pojęcie... Próbowałem doszukiwać się problemu w kolejności przy przeciążanych operatów... nic. tego co powiedział kolega wyżej... nic. czy undefined behavior'ach... nic. Problem leży gdzieś głębiej czy indziej. |
|
Monika90 |
» 2015-10-21 12:06:50 Kolejność wartościowania podwyrażeń jest nieokreślona (poza pewnymi wyjątkami: || && ?: ,). Więc jeżeli masz kod taki jak ten cout << f() << g() << h() << endl;
to nie wiesz w jakiej kolejności wywołane zostaną funkcje f, g i h. Kompilator może wybrać jedną z 6 możliwości, co więcej, nie musi to być za każdym razem ta sama kolejność. Jeżeli te podwyrażenia to nie są wywołania funkcji (np. użycie wartości lub modyfikacja zmiennej typu int), to jest jeszcze gorzej, bo w ogóle nie ma żadnej kolejności. A gdy nie ma kolejności między takimi operacjami, jak zapis i odczyt tej samej zmiennej (typu skalarnego), albo dwa zapisy do tej samej zmiennej (typu skalarnego), to zachowanie programu jest niezdefiniowane. |
|
« 1 » |