" in C ++?" /> " in C ++?" />

21 Domanda: Qual è l'operatore "->" in C ++?

domanda creata a Mon, Feb 13, 2017 12:00 AM

Dopo aver letto Funzionalità nascoste e Dark Corners di C ++ /STL su comp.lang.c++.moderated, sono rimasto completamente sorpreso dal fatto che il seguente frammento di codice abbia compilato e lavorato 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);
    }
}

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

    
8347
  1. O anche solo una corretta spaziatura ... Non penso di aver mai visto uno spazio tra la variabile e ++ o -- prima ...
    2009-10-29 07: 09: 47Z
  2. Questo operatore "goes to" può essere ripristinato (0 < - x). E c'è anche un operatore "corre verso" (0 < ---- x). Accidenti, la cosa più divertente che abbia mai sentito di c ++ sintassi =) +1 per la domanda.
    2009-10-29 07: 27: 21Z
  3. Stranamente, anche se l'interpretazione è molto errata, descrive ciò che il codice fa correttamente. :)
    2009-11-11 13: 51: 39Z
  4. Immagina le nuove possibilità di sintassi: #define upto ++<, #define downto -->. Se ti senti male, puoi fare #define for while( e #define do ) { (e #define done ;}) e scrivere for x downto 0 do printf("%d\n", x) done Oh, l'umanità ...
    2010-03-04 07: 07: 25Z
  5. Apre la possibilità di un nuovo modo espressivo di codifica, vale la pena sacrificare alcuni avvisi del compilatore per: bool CheckNegative (int x) {return x < 0? vero falso ); }
    2012-05-28 11: 12: 58Z
21 risposte                              21                         

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

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

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

 
while( (x--) > 0 )
    
8030
2018-12-23 15: 46: 05Z
  1. Quindi, di nuovo sembra un qualche tipo di operatore di intervallo in quel contesto.
    2009-10-29 07: 14: 52Z
  2. Dire che x è post-decrementato e quindi confrontato con 0 equivale a dire che x viene decrementato dopo essere comparato a 0
    2009-10-29 08: 35: 27Z
  3. Non penso che sia lo stesso. Penso che la parola "then" implichi che ci sia un ordine (dopo il decremento del post, il valore di x è uno in meno). Penso che uno possa dire "Stai post decrescente x e poi confronti il ​​suo vecchio valore e 0 ..." per renderlo più chiaro. Ma questo è il pignolo comunque. Sappiamo tutti cosa si intende.
    2010-01-30 17: 42: 40Z
  4. In Java compila anche:)
    2013-02-12 08: 07: 27Z
  5. Il nome per esso, @ Jay, è uno stile di programmazione scorretto :-) Ciò è evidenziato dal fatto che la domanda è stata posta in primo luogo. Ha molto più senso legare manualmente gli operatori alla cosa su cui stanno operando piuttosto che a qualcosa di non correlato, quindi while (x-- > 0) sarebbe più adatto. Rende anche più ovvio cosa sta succedendo (almeno in un editor di font fissi), il che significa che le parentesi in questa risposta non sarebberonecessario.
    2016-02-15 01: 28: 00Z

O per qualcosa di completamente diverso ... x diapositive su 0

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

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

    
2771
2018-10-09 06: 55: 47Z
  1. Scusa, non capisco questo. Come funziona?
    2012-03-07 10: 48: 26Z
  2. @ mafutrct - Come lo ricordo \in C aggiunge semplicemente la riga successiva come se non ci fosse un'interruzione di riga. I \s qui fondamentalmente non fanno nulla.
    2012-03-10 04: 37: 36Z
  3. IIRC, K &RC ha consentito spazi bianchi tra i "-s" dell'operatore di decremento, nel qual caso potresti avere i backslash nel mezzo di esso, il che sembrerebbe ancora più fresco. :)
    2013-07-13 09: 23: 17Z
  4. @ ArnavBorborah è una vecchia espressione che significa why waste words when a picture does a better job, usata come uno scherzo in questo contesto. (ci sono infatti 2 parole chiave while e printf)
    11-09-2016 11: 36: 46Z
  5. Ah sì, l'oscuro operatore di diapositive. Come potrei dimenticare!
    2017-10-27 10: 00: 48Z

È un operatore molto complicato, quindi anche ISO /IEC JTC1 (Comitato tecnico congiunto 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.

    
2301
2017-03-02 06: 49: 17Z

È 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
}
    
1219
2018-11-06 17: 27: 12Z
  1. Non è giusto. Il valore di x all'interno del corpo del loop è diverso nel secondo caso. La dichiarazione di assegnazione nel tuo esempio dovrebbe essere sopra la logica per essere equivalente. Postfix - sottrae 1, ma il confronto avverrà con il valore da prima la sottrazione.
    2018-10-16 16: 03: 48Z
  2. @ uliwitness Questi sono veramente equivalenti. Sarebbe sbagliato se si usasse il prefisso: 0 >-- x In questo caso il x viene decrementato prima della logica. In postfix, la logica viene eseguita prima del decremento e quindi entrambi i campioni sono equivalenti. Sentiti libero di scriverli in un Console e testarli.
    2019-01-02 19: 36: 20Z
  3. Non sono ancora equivalenti. Dopo il primo ciclo, x è -1 (o overflown nel caso in cui non sia firmato), dopo il secondo, è 0. (Supponendo che x inizi non-negativi, né il ciclo modifica x o interrompe o ...)
    2019-01-15 14: 56: 57Z

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

;)

    
1049
2017-10-11 02: 51: 48Z
  1. quale sistema operativo, questo tipo di output generato, sto usando un ubuntu 12.04 in cui ho avuto un messaggio di errore
    2015-01-19 12: 13: 36Z
  2. Anche se dovrebbe essere ovvio, per tutti coloro che sono nuovi al C ++ leggendo questo: non farlo. Usa il compito aumentato se hai bisogno di incrementare /decrementare di più di uno.
    2015-03-26 02: 41: 40Z
  3. Zero con "laser". while (0 > - - - - - - - - - - ---------- x) ... stesso risultato.
    2016-03-09 21: 54: 16Z
  4. @ phord sei sicuro che non si compili? - > coliru.stacked-crooked.com/a/5aa89a65e3a86c98
    2016-03-24 10: 43: 16Z
  5. @ doc Compilare in c ++, ma non in c.
    2016-03-25 14: 58: 46Z

E '

 
#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.

    
528
2018-03-08 17: 02: 25Z

L'uso di --> ha rilevanza storica. Il decremento era (e lo è ancora in alcuni casi), più veloce dell'incremento sull'architettura x86. L'utilizzo del --> suggerisce che x sta per 0 e fa appello a coloro che hanno background matematici.

    
398
18/11/2009 12: 47: 41Z
  1. Non esattamente vero. Il decremento e l'incremento richiedono lo stesso tempo, il vantaggio di questo è che il confronto a zero è molto veloce rispetto al confronto rispetto a una variabile. Questo è vero per molte architetture, non solo per x86. Qualunque cosa abbia un'istruzione JZ (salta se zero). Girando attorno a te puoi trovare molti loop "for" che vengono scritti all'indietro per salvare cicli sul confronto. Questo è particolarmente veloce su x86 in quanto l'atto di decrementare la variabile imposta il flag di zero in modo appropriato, in modo da poterlo dirottare senza dover confrontare esplicitamente la variabile.
    2009-12-30 05: 16: 46Z
  2. Bene, decrementare verso zero significa che devi solo confrontare 0 per iterazione del ciclo, mentre iterare verso n significa confrontarlo con n ogni iterazione. Il primo tende ad essere più semplice (e su alcune architetture, viene automaticamente testato dopo ogni operazione di registrazione dei dati).
    2010-04-12 15: 07: 58Z
  3. @ burrito Sebbene non sia in disaccordo, i cicli condizionati su valori diversi da zero generalmente vengono predicati in modo quasi perfetto.
    2014-01-11 09: 05: 12Z
  4. L'incremento e il decremento sono ugualmente veloci, probabilmente su tutte le piattaforme (sicuramente su x86). La differenza sta nel testare la condizione di fine del ciclo. Per vedere se il contatore ha raggiunto lo zero è praticamente gratis - quando si decrementa un valore, viene impostato un flag di zero nel processore e per rilevare la condizione di fine è sufficiente controllare quel flag mentre quando si incrementa un'operazione di confronto è richiesta prima della condizione di fine può essere rilevato.
    2015-02-18 11: 14: 01Z
  5. Naturalmente, tutto questo è discutibile in questi giorni, dal momento che i compilatori moderni possono vettorializzare e riveriresi loop automaticamente.
    2015-02-20 03: 53: 56Z
 
while( x-- > 0 )

è il modo in cui viene analizzato.

    
345
2009-11-19 19: 46: 56Z

Assolutamente geek, ma lo userò:

 
#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;
}
    
333
2011-12-03 02: 33: 05Z
  1. Spero di non incontrare mai il tuo codice sorgente ...
    2012-08-15 01: 44: 31Z
  2. @ Mk12 Questo non è il codice sorgente ... è geroglifico: -)
    2012-09-07 03: 27: 35Z
  3. @ SAFX - Sarebbe perfettamente geroglifico con parentesi egiziane
    2012-11-14 10: 00: 02Z
  4. Questo non viene compilato. C non è Pascal, dove l'interno di do ... while è un elenco di istruzioni. In C è un blocco, quindi deve essere do { ... } while.
    2016-09-11 02: 20: 23Z
  5. @ EJP lo fa compilare. La sintassi è do statement while ( expression ) ;. Detto questo, spero che sia capito intendevo l'esempio come uno scherzo.
    2016-10-18 17: 28: 10Z

Un libro che ho letto (non ricordo correttamente quale libro) ha dichiarato: I compilatori cercano di analizzare le espressioni per il token più grande utilizzando 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 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 ^^

    
304
2015-04-23 09: 02: 58Z
  1. La tua seconda spiegazione non è corretta. Il compilatore vedrà a-----b e penserà (a--)-- - b, che non viene compilato perché a-- non restituisce un lvalue.
    2010-05-05 15: 26: 03Z
  2. Inoltre, x e -- sono due token separati.
    2010-07-02 19: 20: 05Z
  3. Questo è noto come Maximal munch .
    2014-03-13 11: 09: 26Z
  4. @ DoctorT: passa il lexer. solo il passaggio semantico è in grado di emmettere quell'errore. quindi la sua spiegazione è corretta.
    2014-09-01 03: 34: 53Z
  5. Finché pensi che --> sia un operatore (che è quello che è implicito avendo la domanda che è stata posta), questa risposta non è affatto utile - tu think token 2 è -->, non solo --. Se sai che --> non è un operatore, probabilmente non hai problemi a capire il codice nella domanda, quindi, a meno che tu non abbia una domanda completamente diversa, non sono sicuro di come possa essere utile.
    2015-05-22 12: 33: 43Z

Questo è esattamente lo stesso di

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

per i numeri non negativi

    
253
2015-04-30 22: 48: 34Z
  1. Non dovrebbe essere for(--x++;--x;++x--)?
    2011-12-04 21: 32: 19Z
  2. @ DoctorT è ciò che unsigned è per
    2013-03-23 ​​18: 39: 13Z
  3. @ MateenUlhaq, che è sbagliato secondo lo standard, l'espressione --x++ ha un comportamento non definito secondo §1.9.15
    2015-06-19 02: 02: 01Z
  4. Se usasse unsigned, avrebbe usato %u
    2019-02-21 22: 01: 27Z

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 del "for (x = 10; x > 0; x --)" su alcune piattaforme.

    
230
2013-02-28 17: 28: 13Z
  1. Va a non essere vero sempre specialmente quando il valore di x è negativo.
    2009-11-13 03: 22: 41Z
  2. L'altra versione non fa la stessa cosa - con for (size_t x=10; x-->0; ) il corpo del ciclo viene eseguito con 9,8, .., 0 mentre l'altra versione ha 10, 9, .., 1. È piuttosto complicato uscire da un ciclo fino a zero con una variabile senza segno altrimenti.
    2010-06-21 08: 57: 44Z
  3. Penso che questo sia un po 'fuorviante ... Non abbiamo un operatore letteralmente "va a", dal momento che abbiamo bisogno di un altro ++> per fare il lavoro incrementale.
    2013-06-15 02: 49: 10Z
  4. @ Josh: in realtà, l'overflow dà un comportamento indefinito per int, quindi potrebbe altrettanto facilmente mangiare il tuo cane come prendere x a zero se inizia in negativo.
    2013-12-06 06: 57: 56Z
  5. Questo è un idioma molto importante per me per il motivo dato nel comnmet di @PeteKirkham, poiché spesso ho bisogno di fare loop decrescenti su quantità senza segno fino a 0 . (Per confronto, l'idioma di omettere i test per zero, come scrivere while (n--) invece per n senza segno, non ti compra nulla e per me ostacola notevolmente la leggibilità.) Ha anche la proprietà piacevole che tu specifichi un altro rispetto all'indice iniziale, che di solito è ciò che si desidera (ad esempio, per un ciclo su un array si specifica la sua dimensione). Mi piace anche il --> senza spazio, in quanto rende l'idioma facile da riconoscere.
    2014-08-30 20: 08: 39Z

Questo codice confronta prima x e 0 e quindi decrementa x. (Detto anche 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 poi 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;
}

Questo risultato è:

 
9 8 7 6 5 4 3 2 1
    
212
2016-01-03 17: 48: 14Z

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 expeCTED. while( x-- > 0 ) significa in realtà while( x > 0). Il x-- post decrementi 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".

    
167
2015-04-30 22: 49: 12Z
  1. Il risultato è solo indefinito quando si incrementa /decrementa la stessa variabile più di una volta nella stessa dichiarazione. Non si applica a questa situazione.
    2010-05-05 15: 30: 19Z
  2. while( x-- > 0 ) actually means while( x > 0) - Non sono sicuro di cosa stavi cercando di dire lì, ma il modo in cui hai formulato implica che il -- non ha alcun significato, il che è ovviamente molto sbagliato.
    2015-05-22 12: 28: 30Z

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

    
138
2010-11-22 19: 02: 21Z
  1. Lo spazio non manca - C (++) ignora gli spazi.
    2012-08-02 19: 16: 31Z
  2. @ H2CO3 Questo non è vero in generale. Esistono luoghi in cui è necessario utilizzare lo spazio bianco per separare i token, ad es. in #define foo() contro #define foo ().
    2013-04-25 21: 16: 44Z
  3. @ Jens Che ne dici: "Lo spazio non manca - C (++) ignora lo spazio bianco non necessario."?
    2013-12-04 20: 35: 14Z

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

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

    
129
2011-10-29 21: 42: 06Z
  1. Sono applicati come i 2 operatori separati che sono. Sono solo scritti in modo fuorviante per sembrare "uno solo".
    2016-11-12 17: 56: 09Z

È una combinazione di due operatori. Il primo -- serve per decrementare il valore e > per verificare se il valore è maggiore dell'operando di destra.

 
#include<stdio.h>

int main()
{
    int x = 10;

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

    return 0;
}

L'output sarà:

 
9 8 7 6 5 4 3 2 1 0            
    
123
2015-04-30 22: 50: 01Z

In realtà, x è post-decremento e con questa condizione viene controllato. Non è -->, è (x--) > 0

Nota: il valore di x viene modificato dopo che la condizione è stata verificata, in quanto post-decremento. Alcuni casi simili possono anche verificarsi, ad esempio:

 
-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0
    
117
2014-04-12 09: 52: 33Z
  1. Tranne che ++ > difficilmente può essere usato in un istante (). Un operatore "va su a ..." sarebbe ++ &lt ;, che non sembra altrettanto bello. L'operatore - > è una felice coincidenza.
    2014-09-01 09: 46: 25Z
  2. Potrebbe funzionare anche il while (0 <-- x), quindi?
    2015-06-15 14: 00: 33Z
  3. @ BenLeggiero Questo potrebbe 'funzionare' nel senso di generare codice che fa qualcosa (mentre fa infuriare i lettori a cui non piace il codice faux-clever), ma la semantica è diverso, poiché il suo uso di predecrement implica l'esecuzione di un numero minore di iterazioni. Come esempio forzato, non avrebbe mai eseguito il corpo del loop se x fosse partito a 1, ma sarebbe stato while ( (x--) > 0 ). {edit} Eric Lippert ha trattato entrambi nelle sue note di rilascio del C # 4: blogs.msdn.microsoft.com/ericlippert/2010/04/01/...
    2016-11-12 17: 57: 29Z

C e C ++ obbedire alla regola" maximum munch ". Allo stesso modo a --- b viene tradotto in (a--) - b, nel tuo caso x-->0 si traduce in (x--)>0.

Ciò che la regola dice essenzialmente è che andando da sinistra a destra, le espressioni sono formate prendendo il massimo di caratteri che formeranno un'espressione valida.

    
113
2014-04-12 09: 55: 16Z
  1. Quale è ciò che l'OP assunse: che "((a) - >)" era il massimo munch. Si scopre che l'ipotesi originale dell'OP non era corretta: "- >" non è un operatore valido al massimo.
    2014-08-28 00: 41: 45Z
  2. Anche noto come parsing avido, se ricordo male.
    2015-07-11 01: 04: 15Z
  3. @ RoyTinker Greedy scanning. Il parser non ha nulla a che fare con questo.
    2016-09-11 02: 21: 50Z

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.

Il x-- è solo una scorciatoia per quanto sopra, e > è solo un normale superiore a operator. Nessun grande mistero!

Al giorno d'oggi ci sono troppe persone che complicano le cose semplici;)

    
26
2018-06-30 10: 10: 56Z
  1. Questa domanda non riguarda le complicazioni, ma circa ** Caratteristiche nascoste e Dark Corners di C ++ /STL **
    2016-10-27 15: 32: 01Z
  2. Il programma qui fornisce un output diverso rispetto all'originale perché x qui viene decrementato dopo printf. Ciò dimostra bene come "le risposte semplici" siano in genere errate.
    2017-05-13 09: 30: 30Z
  3. The OP's way: 9 8 7 6 5 4 3 2 1 0 e The Garry_G way: 10 9 8 7 6 5 4 3 2 1
    2017-12-15 18: 33: 22Z
  4. Non fa la stessa cosa. Sposta il x=x-1 prima del printf, quindi puoi dire "fa la stessa cosa".
    2019-01-05 17: 05: 49Z

Nel modo convenzionale definiremmo una condizione nella parentesi while di loop () e una condizione di terminazione all'interno delle parentesi graffe {}, ma --> definisce entrambe contemporaneamente.

Ad esempio:

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

Questo decrementa a ed esegue il ciclo mentre a è maggiore di 0.

convenzionalely, sarebbe come:

 
int abc(void)
{
    int a = 5;
    while(a > 0)
    {
        a--;
        // Code
    }
    a--;
}

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

    
23
2019-06-15 19: 35: 13Z
  1. Questo non è corretto. Il codice nella domanda è: 'test-write-execute' (prova prima, scrivi nuovo valore, esegui il ciclo), il tuo esempio è 'test-execute-write'.
    2017-07-14 19: 07: 40Z
  2. @ v010dya Risolto il problema, ora è test-write-execute come nella domanda, grazie per aver segnalato!
    2019-05-12 10: 59: 49Z
  3. @ VladislavToncharov La tua modifica era ancora sbagliata. Vedi il mio.
    2019-06-15 19: 36: 17Z
fonte posta Qui