Operatory inkrementacji i dekrementacji

Operatory inkrementacji i dekrementacji to operatory jednoargumentowe , które odpowiednio dodają lub odejmują jedynkę do lub od swojego operandu .

Są one powszechnie realizowane w imperatywnych językach programowania . Języki podobne do C zawierają dwie wersje (pre- i post-) każdego operatora z nieco inną semantyką.

W językach składniowo wywodzących się z B (w tym C i jego różnych pochodnych) operator inkrementacji jest zapisywany jako ++ , a operator dekrementacji jest zapisywany jako -- . Kilka innych języków używa funkcji inc(x) i dec(x).

Operator inkrementacji zwiększa, a operator dekrementu zmniejsza wartość swojego operandu o 1. Operand musi mieć typ danych arytmetycznych lub wskaźnikowych i musi odwoływać się do modyfikowalnego obiektu danych . Wartości wskaźników są zwiększane (lub zmniejszane) o wartość, która powoduje, że wskazują następny (lub poprzedni) element sąsiadujący z pamięcią.

W językach obsługujących obie wersje operatorów:

  • Operatory pre -increment i pre -decrement zwiększają (lub zmniejszają) swój operand o 1, a wartością wyrażenia jest wynikowa wartość zwiększona (lub zmniejszona).
  • Operatory post -increment i post -decrement zwiększają (lub zmniejszają) wartość swojego operandu o 1, ale wartością wyrażenia jest wartość operandu przed operacją inkrementacji (lub dekrementacji).

W językach, w których inkrementacja/zmniejszenie nie jest wyrażeniem (np. Go ), potrzebna jest tylko jedna wersja (w przypadku Go tylko operatorzy pocztowi).

Ponieważ operator zwiększania/zmniejszania modyfikuje swój operand, użycie takiego operandu więcej niż raz w tym samym wyrażeniu może dać niezdefiniowane wyniki. Na przykład w wyrażeniach takich jak x - ++x nie jest jasne, w jakiej kolejności należy wykonywać operacje odejmowania i zwiększania. Takie wyrażenia generalnie wywołują niezdefiniowane zachowanie i należy ich unikać.

W językach z typowanymi wskaźnikami, takimi jak C, operator inkrementacji przesuwa wskaźnik do następnego elementu tego typu — zwiększając wartość wskaźnika o rozmiar tego typu. Kiedy wskaźnik (właściwego typu) wskazuje na dowolny element w tablicy, zwiększanie (lub zmniejszanie) powoduje, że wskaźnik wskazuje „następny” (lub „poprzedni”) element tej tablicy. Gdy wskaźnik ma typ wskaźnika do liczby całkowitej, zwiększanie tego wskaźnika powoduje, że wskazuje on na następną liczbę całkowitą (zwykle zwiększa się o 4 bajty). Gdy wskaźnik ma typ wskaźnika do pracownika, zwiększanie tego wskaźnika powoduje, że wskazuje on na następnego „pracownika” — jeśli rozmiar struktury pracownika wynosi 106 bajtów, zwiększanie tego wskaźnika zwiększa go o 106 bajtów.

Przykłady

Poniższy fragment kodu C ilustruje różnicę między operatorami przed i po inkrementacji i dekrementacji:

 
 



  
      


  
      

 intx  ;  _  int  y  ;  // Operatory inkrementacji  // Preinkrementacja: x jest zwiększane o 1, następnie y jest przypisywana wartość x  x  =  1  ;  y  =  ++  x  ;  // x wynosi teraz 2, y również wynosi 2  // Post-inkrementacja: y ma przypisaną wartość x, następnie x jest zwiększane o 1  x  =  1  ;  y  =  x  ++  ;  // y wynosi 1, x wynosi teraz 2  // Operatory dekrementacji 

  
      


  
       // Wstępne zmniejszenie: x jest zmniejszane o 1, następnie y jest przypisywana wartość x  x  =  1  ;  y  =  --  x  ;  // x wynosi teraz 0, y również wynosi 0  // Post-dekrementacja: y ma przypisaną wartość x, następnie x jest zmniejszane o 1  x  =  1  ;  y  =  x  --  ;  // y wynosi 1, x wynosi teraz 0 

W językach, w których brakuje tych operatorów, równoważne wyniki wymagają dodatkowej linii kodu:


  
      
        


  
        
       # Preinkrementacja: y = ++x  x  =  1  x  =  x  +  1  # x wynosi teraz 2 (można zapisać jako „x += 1” w Pythonie)  y  =  x  # y to także 2  # Postinkrementacja: y = x++  x  =  1  y  =  x  # y wynosi 1  x  =  x  +  1  # x wynosi teraz 2 


Operator postinkrementacji jest często używany z indeksami dolnymi tablic. Na przykład:


    

        
              0

       
              
                            
     
 // Suma elementów tablicy  float  sum_elements  (  float  arr  [],  int  n  )  {  float  sum  =  0.0  ;  int  ja  =  ;  while  (  i  <  n  )  suma  +=  arr  [  i  ++  ];  // Post-inkrementacja i, która  // przechodzi przez n elementów tablicy  return  sum  ;  } 

Operator post-inkrementacji jest również często używany ze wskaźnikami :


      

       0        
             
                           
 // Skopiuj jedną tablicę do innej  void  copy_array  (  float  *  src  ,  float  *  dst  ,  int  n  )  {  while  (  n  --  >  )  // Pętla odliczająca od n do zera  *  dst  ++  =  *  src  ++  ;  // Kopiuje element *(src) do *(dst),  // następnie zwiększa oba wskaźniki  } 

Należy zauważyć, że te przykłady działają również w innych językach podobnych do C, takich jak C++ , Java i C# .

  • Operator inkrementacji można zademonstrować na przykładzie:
     
     
    
           
          
            
         0
     #include  <stdio.h>  int  main  ()  {  int  c  =  2  ;  printf  (  "%d  \n  "  ,  c  ++  );  // ta instrukcja wyświetla 2, następnie c jest zwiększane o 1 do 3.  printf  (  "%d"  ,  ++  c  );  // ta instrukcja zwiększa c o 1, a następnie wyświetla się c.  powrót  ;  } 
    
    • Wyjście:
      
       2  4 
      

Języki pomocnicze

Poniższa lista, choć nie jest kompletna ani wyczerpująca, zawiera niektóre z głównych języków programowania, które obsługują operatory zwiększania/zmniejszania ++ / -- .

Swift firmy Apple obsługiwał kiedyś tych operatorów, ale obsługa została usunięta w wersji 3.)

Pascal , Delphi , Modula-2 i Oberon udostępniają te same funkcje, ale nazywane są inc(x) i dec(x).

Zwłaszcza Python i Rust nie obsługują tych operatorów.

Historia

Koncepcja została wprowadzona do języka programowania B około 1969 roku przez Kena Thompsona .

Thompson poszedł o krok dalej, wymyślając operatory ++ i --, które zwiększają lub zmniejszają; ich pozycja prefiksu lub postfiksu określa, czy zmiana nastąpi przed, czy po zanotowaniu wartości operandu. Nie było ich w najwcześniejszych wersjach B, ale pojawiały się po drodze. Ludzie często domyślają się, że zostały stworzone, aby korzystać z trybów automatycznego zwiększania i automatycznego zmniejszania adresu dostarczanych przez DEC PDP-11, na którym C i Unix stały się popularne. Jest to historycznie niemożliwe, ponieważ nie było PDP-11, kiedy opracowywano B. PDP-7 miał jednak kilka komórek pamięci „automatycznie zwiększanych”, z tą właściwością, że pośrednie odniesienie do pamięci przez nie zwiększało komórkę. Ta funkcja prawdopodobnie zasugerowała Thompsonowi takich operatorów; uogólnienie, aby uczynić je zarówno przedrostkiem, jak i przyrostkiem, było jego własnym. Rzeczywiście, komórki autoinkrementacji nie były używane bezpośrednio w implementacji operatorów, a silniejszą motywacją do innowacji była prawdopodobnie jego obserwacja, że ​​translacja ++x była mniejsza niż translacja x=x+1.

Zobacz też