• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Operatory pre i post inkrmentacji

Object Storage Arubacloud
+1 głos
625 wizyt
pytanie zadane 2 lutego 2017 w C i C++ przez Dexterim Dyskutant (8,370 p.)

Dlaczego to działa tak :)

 

#include <iostream>

int& fun(int &i){
return ++i;
}

int main(){

//…
int a=3, b=3;

std::cout<<a<< " " <<b; //3 3
a=fun(a)++;
std::cout<<a; //4

}

Zastanawiam się czemu a jest równe 4 a nie 5, ktoś umie wytłumaczyć

1 odpowiedź

+1 głos
odpowiedź 2 lutego 2017 przez criss Mędrzec (172,590 p.)
wybrane 2 lutego 2017 przez Dexterim
 
Najlepsza

Bo operator post-inkrementacji zwraca nowego inta o pierwotnej wartości inkrementowanego inta. A operator pre-inkrementacji zwraca referencje na inkrementowaną zmienną.

Na przykładzie kodu:

Weźmy sobie taką strukture. C++ nie pozwala na nadpisywanie operatorów typów wbudowanych, więc ciężko byłoby to sensownie pokazać.

struct Int
{
   int val;
   Int operator++(int); // operator post-inkrementacji
   Int & operator++(); // operator pre-inkrementacji
};

Int Int::operator++(int) //operator post-inkrementacji
{
   Int tmp = *this;
   this->val = this->val + 1;
   return tmp;
}

Int & Int::operator++() //operator pre-inkrementacji
{
   this->val = this->val + 1;
   return *this;
}

Dla rozróżnienia operator post-inkrementacji ma w argumencie symbolicznego inta. Stąd ten int w moim przykładzie.

komentarz 2 lutego 2017 przez Dexterim Dyskutant (8,370 p.)
Okej myślę, że zrozumiałem dzięki ;)
komentarz 2 lutego 2017 przez unknown Nałogowiec (39,560 p.)

Przecież ta linijka:

a=fun(a)++;

sprawia, że kod ma UB

komentarz 2 lutego 2017 przez criss Mędrzec (172,590 p.)
Dlaczego?
komentarz 2 lutego 2017 przez criss Mędrzec (172,590 p.)

Jeszcze dodatkowe wytłumaczenie dla ciebie @Dexterim, bo sam się zamotałem przez chwile jak teraz jeszcze raz spojrzałem.

fun(a)++; faktycznie zwiększa a do wartości 5, ale ostatecznie masz przypisanie a=fun(a)++; więc przypisujesz do a jej własną wartość z przed inkrementacji (bo to post-inkrementacja). Stąd wartość 4 na końcu.

komentarz 2 lutego 2017 przez unknown Nałogowiec (39,560 p.)

Drugi UB związany jest z post-inkrementacją i potencjalnie trywialną linijką a = a++. Jak się okazuje, są tutaj również dwie opcje, które rozważę posługując się kodem pomocniczym w postaci int a = 5; a = a++;.

Terminologia: 
a_mem - a w pamięci (np. jako lokalna zmienna na stosie)
a_copy - kopia a w jakimś podręcznym rejestrze

Opcja 1. Wynikowy kod ma następującą formę (w pseudo-assembly):
Warunki początkowe: (a_mem == 5, a_copy == brak)

Krop 1. Podstawienie a do równania.
a = 5++; (a_mem == 5, a_copy == 5)

Krok 2. Post-inkrementacja na zmiennej w pamięci.
a = 5;   (a_mem == 6, a_copy == 5)

Krok 3. Przypisanie, czyli a_copy leci do a_mem.
(a_mem == 5, a_copy == brak)
W powyższym wypadku wynik post-inkrementacji a zaginął w akcji. Tj. niby zostało zapisane do pamięci, ale po chwili operacja przypisania (=) wrzuciła finalny wynik obliczeń (czyli 5) do zmiennej a w pamięci nadpisując jednocześnie wynik post-inkrementacji. (prawdę mówiąc zawsze uważałem, że operacja post-inkrementacji jest deferowana na sam koniec wszystkich obliczeń, więc uznałbym to zachowanie za bug kompilatora)

Opcja 2. Post-inkrementacja dzieje się po przypisaniu.
Warunki początkowe: (a_mem == 5, a_copy == brak)

Krop 1. Podstawienie a do równania.
a = 5++; (a_mem == 5, a_copy == 5)

Krok 3. Przypisanie, czyli a_copy leci do a_mem.
(zostaje a++) (a_mem == 5, a_copy == brak)

Krok 2. Post-inkrementacja na zmiennej w pamięci.
(a_mem == 6, a_copy == brak)

Czyli post-inkrementacja zostaje faktycznie zdeferowana na koniec obliczeń.

Źródło: http://gynvael.coldwind.pl/?id=369

komentarz 2 lutego 2017 przez unknown Nałogowiec (39,560 p.)
W GCC zmienna a ma wartość 4 a VS 5
komentarz 2 lutego 2017 przez Dexterim Dyskutant (8,370 p.)
Wiem jak to działa tylko na początku referncja zwracana mnie zmyliła @Criss
komentarz 2 lutego 2017 przez criss Mędrzec (172,590 p.)
Hm, no dobra, to dzięki @unknown za poprawienie.

W takim razie moje wytłumaczenie operatorów ++() i ++(int) może pozostać, ale w tej konkretnej sytuacji niczego nie wyjaśnia.

Podobne pytania

0 głosów
1 odpowiedź 474 wizyt
pytanie zadane 11 listopada 2016 w SQL, bazy danych przez kistel66 Początkujący (370 p.)
0 głosów
1 odpowiedź 622 wizyt
0 głosów
1 odpowiedź 151 wizyt
pytanie zadane 9 grudnia 2015 w C i C++ przez PoProstuTomasz Początkujący (470 p.)

92,536 zapytań

141,377 odpowiedzi

319,456 komentarzy

61,922 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...