operators bitwise - Qual è l'operatore "->" in C++?




code-formatting standards-compliance (18)

Dopo aver letto Hidden Features e Dark Corners di C ++ / STL su comp.lang.c++.moderated , sono rimasto completamente sorpreso dal fatto che il seguente snippet fosse compilato e funzionasse sia in Visual Studio 2008 che in G ++ 4.4.

Ecco il codice:

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

Presumo che questo sia C, visto che funziona anche in GCC. Dove è definito nello standard e da dove proviene?


Answers

-- è l'operatore di decremento e > è l'operatore maggiore di .

I due operatori sono applicati come uno solo --> .


Modo convenzionale definiamo la condizione in while parentesi di ciclo " () " e terminando la condizione all'interno delle parentesi " {} ", ma questo -- & > è un modo in cui uno definisce tutto in una volta. Ad esempio:

int abc(){
    int a = 5
    while((a--) > 0){ // Decrement and comparison both at once
        // Code
    }
}

Dice, decrementa a ed esegue il ciclo fino al momento in cui a è maggiore di 0

In un altro modo avrebbe dovuto essere come:

int abc(){
    int a = 5
    while(a > 0){
        // Code
        a = a -1 // Decrement inside loop
    }
}

in entrambi i modi, facciamo la stessa cosa e raggiungiamo gli stessi obiettivi.


Fai attenzione

--> non è un operatore. Sono infatti due operatori separati, -- e > .

Il codice condizionale decrementa x , mentre restituisce il valore originale (non decrementato) di x , quindi confronta il valore originale con 0 usando l'operatore > .

Per capire meglio, la dichiarazione potrebbe essere scritta come segue:

while((x--) > 0)

C e C++ obbediscono alla regola del "massimo sgranocchiare". (a--) - b stesso modo a --- b è tradotto in (a--) - b , nel tuo caso x-->0 traduce in (x--)>0 .

Quello che la regola dice in sostanza è che andando da sinistra a destra, le espressioni si formano prendendo il massimo di caratteri che formeranno un'espressione valida.


Perché tutte le complicazioni?

La semplice risposta alla domanda originale è solo:

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

Fa la stessa cosa Non dicendo che dovresti farlo in questo modo, ma fa la stessa cosa e avrebbe risposto alla domanda in un solo post.

La x-- è semplicemente una scorciatoia per quanto sopra, e > è solo un normale operator maggiore di. Nessun grande mistero!

Ci sono troppe persone che rendono semplici le cose semplici oggigiorno;)


Un libro che ho letto (non ricordo correttamente quale libro) ha dichiarato: I compilatori cercano di analizzare le espressioni per il token più grande usando la regola left right.

In questo caso, l'espressione:

x-->0

Analizza i token più grandi:

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

La stessa regola si applica a questa espressione:

a-----b

Dopo l'analisi:

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

Spero che questo aiuti a capire l'espressione complicata ^^


x può andare a zero ancora più velocemente nella direzione opposta:

int x = 10;

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

8 6 4 2

Puoi controllare la velocità con una freccia!

int x = 100;

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

90 80 70 60 50 40 30 20 10

;)


Questo codice confronta prima x e 0 e quindi decrementa x. (Anche detto nella prima risposta: stai post-decrementando x e poi confronti x e 0 con l'operatore > .) Vedi l'output di questo codice:

9 8 7 6 5 4 3 2 1 0

Ora prima confrontiamo e poi diminuiamo vedendo 0 nell'output.

Se vogliamo prima decrementare e quindi confrontare, usa questo codice:

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

    while( --x> 0 ) // x goes to 0
    {
        printf("%d ", x);
    }
    return 0;
}

Quell'output è:

9 8 7 6 5 4 3 2 1

Assolutamente geek, ma userò questo:

#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;
}

Suo

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

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

       printf("%d ", x);
     }

     return 0;
}

Proprio lo spazio fa sembrare le cose divertenti, -- decrementi e confronti > .


C'è uno spazio mancante tra -- e > . x è post decrementato, cioè decrementato dopo aver controllato la condizione x>0 ? .


Questo è esattamente lo stesso di

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

per numeri non negativi


O per qualcosa di completamente diverso ... x fa scorrere a 0

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

Non così matematico, ma ... ogni immagine dipinge un migliaio di parole ...


Questo è un operatore molto complicato, quindi anche ISO / IEC JTC1 (Joint Technical Committee 1) ha inserito la sua descrizione in due parti diverse dello standard C ++.

A parte gli scherzi, sono due operatori diversi: -- e > descritti rispettivamente in §5.2.6 / 2 e §5.9 dello standard C ++ 03.


È equivalente a

while (x-- > 0)

x-- (post decremento) è equivalente a x = x-1 quindi, il codice si trasforma in:

while(x > 0) {
    x = x-1;
    // logic
}

Il mio compilatore stamperà 9876543210 quando eseguo questo codice.

#include <iostream>
int main()
{
    int x = 10;

    while( x --> 0 ) // x goes to 0
    {
        std::cout << x;
    }
}

Come previsto. Il while( x-- > 0 ) realtà significa while( x > 0) . Il x-- post decrementa x .

while( x > 0 ) 
{
    x--;
    std::cout << x;
}

è un modo diverso di scrivere la stessa cosa

È bello che l'originale abbia l'aspetto di "mentre x va a 0".


Ad ogni modo, abbiamo un operatore "va a" ora. "-->" è facile da ricordare come una direzione e "mentre x va a zero" ha un significato diretto.

Inoltre, è un po 'più efficiente di "for (x = 10; x > 0; x --)" su alcune piattaforme.


Mi sembra che ci sia ancora un altro punto che non è stato trattato qui.

A differenza dei puntatori, i riferimenti sono sintatticamente equivalenti all'oggetto a cui si riferiscono, cioè qualsiasi operazione che può essere applicata a un oggetto funziona per un riferimento e con la stessa sintassi esatta (l'eccezione è ovviamente l'inizializzazione).

Anche se questo può sembrare superficiale, credo che questa proprietà sia cruciale per un certo numero di funzionalità C ++, ad esempio:

  • Modelli . Poiché i parametri del modello sono tipografici anatra, le proprietà sintattiche di un tipo sono tutto ciò che conta, così spesso lo stesso modello può essere utilizzato con entrambi Te T&.
    (o std::reference_wrapper<T>che si basa ancora su un cast implicito su T&)
    Modelli che coprono entrambi T&e T&&sono ancora più comuni.

  • Lvalues . Considera la frase str[0] = 'X';Senza riferimenti, funzionerebbe solo con c-string ( char* str). Restituire il carattere per riferimento consente alle classi definite dall'utente di avere la stessa notazione.

  • Copia i costruttori . Sintatticamente ha senso passare gli oggetti per copiare i costruttori e non i puntatori agli oggetti. Ma non c'è un modo per un costruttore di copia di prendere un oggetto in base al valore: ciò comporterebbe una chiamata ricorsiva allo stesso costruttore di copie. Questo lascia i riferimenti come l'unica opzione qui.

  • Sovraccarichi operatore . Con i riferimenti è possibile introdurre l'indirezione indiretta a una chiamata dell'operatore, ad esempio operator+(const T& a, const T& b)mantenendo la stessa notazione infissa. Questo funziona anche per funzioni regolari sovraccariche.

Questi punti potenziano una parte considerevole del C ++ e della libreria standard, quindi questa è una proprietà piuttosto importante dei riferimenti.





c++ operators code-formatting standards-compliance