Pytanie Co to jest operator "->" w C ++?


Po odczytaniu Ukryte funkcje i Dark Corners C ++ / STL na comp.lang.c++.moderatedByłem całkowicie zaskoczony, że poniższy fragment został skompilowany i działał zarówno w Visual Studio 2008, jak i G ++ 4.4.

Oto kod:

#include <stdio.h>
int main()
{
    int x = 10;
    while (x --> 0) // x goes to 0
    {
        printf("%d ", x);
    }
}

Zakładam, że to C, ponieważ działa również w GCC. Gdzie jest to zdefiniowane w standardzie i skąd ono pochodzi?


7782


pochodzenie


A nawet po prostu właściwe odstępy ... Nie sądzę, żebym kiedykolwiek widział przestrzeń między zmienną a którąkolwiek ++ lub -- przed... - Matthew Scharley
Ten operator "idzie do" może zostać cofnięty (0 <- x). A także jest operator "biegnie do" (0 <---- x). Geez, najśmieszniejsza rzecz, jaką słyszałem o c ++ składni =) +1 dla pytania. - SadSido
Co zabawne, chociaż interpretacja jest bardzo zła, opisuje to, co właściwie robi kod. :) - Noldorin
Wyobraź sobie nowe możliwości składni: #define upto ++<, #define downto -->. Jeśli czujesz się zły, możesz to zrobić #define for while( i #define do ) { (i #define done ;}) i napisz for x downto 0 do printf("%d\n", x) done Oh ludzkość... - Chris Lutz
Otwiera możliwość zupełnie nowego, ekspresyjnego sposobu kodowania, warte poświęcenia kilku ostrzeżeń kompilatora dla: bool CheckNegative (int x) {return x <0? prawda fałsz ); } - ttt


Odpowiedzi:


--> nie jest operatorem. To w rzeczywistości dwa oddzielne podmioty, -- i >.

Kod warunkowy ulega zmniejszeniu x, wracając xoryginalną (nie zmniejszoną) wartość, a następnie porównuje oryginalną wartość z 0 używając > operator.

Aby lepiej zrozumieć, oświadczenie można zapisać w następujący sposób:

while( (x--) > 0 )

7479



Z drugiej strony wygląda to trochę jak operator zakresu w tym kontekście. - Charles Salvia
Mówienie, że x jest po zmniejszeniu, a następnie porównane do 0, jest tym samym, co powiedzenie x jest zmniejszane po porównaniu do 0 - Charles Salvia
W Javie także kompiluje :) - Steven Devijver
Nazwa, @Jay, to zły styl programowania :-) Dowodzi tego fakt, że pytanie zostało zadane w pierwszej kolejności. Bardziej sensowne jest, aby tekstowo wiązać operatorów do rzeczy, na których działają, niż do czegoś niezwiązanego, więc while (x-- > 0) byłoby bardziej trafne. Ułatwia to również to, co się dzieje (przynajmniej w edytorze czcionek stałych), co oznacza, że ​​nawiasy w tej odpowiedzi nie będą konieczne. - paxdiablo
Aby wyjaśnić operator "->", musisz użyć operatora "((" operator "i" -)> "? - Ira Baxter


Lub coś zupełnie innego ... x slajdy do 0

while (x --\
            \
             \
              \
               > 0)
     printf("%d ", x);

Nie tak matematycznie, ale ... każde zdjęcie przedstawia tysiąc słów. ...


2382



Przepraszam, nie dostaję tego. Jak to działa? - mafu
@mafutrct - jak pamiętam \ in C dodaje kolejne wiersze tak, jakby nie było linii podziału. \ S tutaj w zasadzie nic nie robią. - Hogan
IIRC, K i R C zezwalały na odstępy między znakami "-'s" w operatorze dekrementacji, w którym to przypadku mógłbyś mieć odwrócone ukośniki w środku, które wyglądałyby jeszcze fajniej. :) - Jules
@ArnavBorborah to stare znaczenie wypowiedzi why waste words when a picture does a better job , używane jako żart w tym kontekście. (są w rzeczywistości 2 słowa kluczowe while i printf ) - unsynchronized
Ach tak, niejasny operator slajdu. Jak mogłem zapomnieć! - demonkoryu


To bardzo skomplikowany operator, więc nawet ISO / IEC JTC1 (Wspólny Komitet Techniczny 1) umieścił swój opis w dwóch różnych częściach standardu C ++.

Żarty na bok, są dwoma różnymi operatorami: -- i > opisane odpowiednio w §5.2.6 / 2 i §5.9 normy C ++ 03.


2221





To odpowiednik

while (x-- > 0)

1142



Chociaż może to pomóc wielu w zrozumieniu kodu, pomocne będzie kilka linii wyjaśniających go poprawnie. - Dukeling
@Dukeling x-- jest krótką notacją dla x-1 - Albert Renshaw
@AlbertRenshaw Jestem pewna, że ​​stary komentarz, na który odpowiedziałaś, oznaczał, że wyjaśnienie, że nie jest to pojedynczy operator, a raczej dwóch operatorów, którzy byli wprowadzeni w błąd, byłoby pomocne. - mah
@ mbomb007 Przepraszam, chciałem powiedzieć x- = 1 - było spóźnione haha - Albert Renshaw
@AlbertRenshaw but x -= 1 i x-- nie są takie same ... Jeśli chcesz napisać to tak, to musi być while (x >= 0) { x -= 1; } - Krzysztof Karski


x można przejść do zera jeszcze szybciej w przeciwnym kierunku:

int x = 10;

while( 0 <---- x )
{
   printf("%d ", x);
}

8 6 4 2

Możesz kontrolować prędkość za pomocą strzałki!

int x = 100;

while( 0 <-------------------- x )
{
   printf("%d ", x);
}

90 80 70 60 50 40 30 20 10

;)


861



który system operacyjny, ten typ generowanego wyjścia, używam Ubuntu 12.04 w tym, że miałem komunikat o błędzie - Bhuvanesh
Chociaż powinno to być oczywiste dla każdego nowego w C ++: nie rób tego. Po prostu użyj rozszerzonego zadania, jeśli chcesz zwiększyć / zmniejszyć o więcej niż jeden. - Blimeo
Zero za pomocą "laserów". while (0> - - - - - - - - - - ---------- x) ... ten sam wynik. - Samuel Danielson
@phord czy jesteś pewien, że się nie kompiluje? -> coliru.stacked-crooked.com/a/5aa89a65e3a86c98 - doc
@doc Kompiluje się w C ++, ale nie w c. - phord


Jego

#include <stdio.h>
int main(void){
     int x = 10;

     while( x-- > 0 ){ // x goes to 0

       printf("%d ", x);
     }

     return 0;
}

Tylko przestrzeń sprawia, że ​​rzeczy wyglądają śmiesznie, -- dekrementy i > porównuje.


498





Wykorzystanie --> ma znaczenie historyczne. Zmniejszanie było (i nadal jest w niektórych przypadkach) szybsze niż inkrementowanie architektury x86. Za pomocą --> sugeruje, że x zamierza 0i apeluje do osób o matematycznym pochodzeniu.


372



Niezupełnie prawda. Zmniejszanie i Inkrementowanie trwa tyle samo czasu, a korzyścią jest to, że porównanie do zera jest bardzo szybkie w porównaniu do porównania w porównaniu ze zmienną. Dotyczy to wielu architektur, nie tylko x86. Wszystko z instrukcją JZ (przeskocz jeśli zero). Wałęsając się możesz znaleźć wiele pętli "dla", które są zapisywane do tyłu, aby oszczędzać cykle podczas porównywania. Jest to szczególnie szybkie na x86, ponieważ akt zmniejszania zmiennej odpowiednio ustawiał flagę zerową, abyś mógł następnie rozgałęzić bez konieczności jednoznacznego porównywania zmiennej. - burito
Cóż, zmniejszanie w kierunku zera oznacza, że ​​musisz tylko porównać z 0 na pętlę iteracji, podczas gdy iteracja w kierunku n oznacza porównanie z każdą iteracją. Ten pierwszy wydaje się łatwiejszy (a na niektórych architekturach jest automatycznie testowany po każdym uruchomieniu rejestru danych). - Joey Adams
@burrito Chociaż nie zgadzam się, pętle warunkowane na wartościach niezerowych ogólnie dają się przewidzieć prawie idealnie. - Duncan
Przyrost i dekrementacja są równie szybkie, prawdopodobnie na wszystkich platformach (zdecydowanie na x86). Różnica polega na testowaniu warunku końca pętli. Aby sprawdzić, czy licznik osiągnął zero, jest praktycznie wolny - po zmniejszeniu wartości ustawiana jest flaga zerowa w procesorze, a w celu wykrycia warunku końcowego wystarczy sprawdzić flagę, natomiast w przypadku inkrementacji wymagana jest operacja porównania przed zakończeniem warunku można wykryć. - lego
Oczywiście, w dzisiejszych czasach wszystko to jest dyskusyjne, ponieważ nowoczesne kompilatory mogą automatycznie wektoryzować i odwracać pętle. - Lambda Fairy


while( x-- > 0 )

jest to, jak to jest analizowane.


324





Zupełnie geek, ale będę tego używać:

#define as ;while

int main(int argc, char* argv[])
{
    int n = atoi(argv[1]);
    do printf("n is %d\n", n) as ( n --> 0);
    return 0;
}

292



Mam nadzieję, że nigdy nie natknę się na żaden kod źródłowy ... - mk12
@ Mk12 To nie jest kod źródłowy ... to hieroglify :-) - raffian
@SAFX - Byłoby idealnie hieroglify z nawiasy egipskie - mouviciel
To się nie kompiluje. C to nie Pascal, gdzie wnętrze do ... while to lista instrukcji. W C jest blok, więc musi być do { ... } while. - user207421
@EJP to kompiluje. Składnia jest do statement while ( expression ) ;. Powiedziawszy to, mam nadzieję, że zrozumiano, że miałem na myśli przykład jako żart. - Escualo


Jedna książka, którą przeczytałem (nie pamiętam poprawnie, którą książkę) stwierdzała: Kompilatory próbują parsować wyrażenia do największego tokena za pomocą prawej lewej reguły.

W tym przypadku wyrażenie:

x-->0

Parse do największych tokenów:

token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0

Ta sama zasada dotyczy tego wyrażenia:

a-----b

Po przeanalizowaniu:

token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b

Mam nadzieję, że pomoże to zrozumieć skomplikowaną ekspresję ^^


283



Twoje drugie wyjaśnienie nie jest poprawne. Kompilator zobaczy a-----b i pomyśleć (a--)-- - b, który nie kompiluje, ponieważ a-- nie zwraca wartości l. - Tim Leaf
Do tego, x i -- są dwoma oddzielnymi tokenami. - Roland Illig
Jest to znane jako Maksymalne chrupnięcie. - RJFalconer
@DoctorT: mija lexer. tylko semantyczna przepustka jest w stanie wywołać ten błąd. więc jego wyjaśnienie jest poprawne. - v.oddou
Tak długo, jak myślisz --> jest operatorem (co jest implikowane przez pytanie, które zostało zadane), ta odpowiedź w ogóle nie jest pomocna - pomyślisz, że token 2 to -->, nie tylko --. Jeśli to wiesz --> nie jest operatorem, prawdopodobnie nie masz problemu ze zrozumieniem kodu w pytaniu, więc jeśli nie masz zupełnie innego pytania, nie jestem pewien, w jaki sposób może to być przydatne. - Dukeling