Domanda

Ho visto dei loop molto strani per for durante la lettura del codice di altre persone. Ho provato a cercare una spiegazione completa della sintassi per il ciclo for in C ma è molto difficile perché la parola " per " ; appare in frasi non correlate che rendono la ricerca quasi impossibile per Google in modo efficace.

Questa domanda mi è venuta in mente dopo aver letto questa discussione che mi ha incuriosito di nuovo.

Il per qui:

for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

Nella condizione centrale c'è una virgola che separa i due pezzi di codice, cosa fa questa virgola? Capisco la virgola sul lato destro poiché rende sia a > > = 1 che b < < = 1 .

Ma all'interno di una condizione di uscita ad anello, cosa succede? Esce quando p == 0 , quando a == 1 o quando si verificano entrambi?

Sarebbe bello se qualcuno potesse aiutarmi a capirlo e magari indicarmi la direzione di una descrizione completa della sintassi del ciclo for .

È stato utile?

Soluzione

La virgola non è esclusiva di for loop; è l'operatore virgola.

x = (a, b);

eseguirà prima a, quindi b, quindi imposta x sul valore di b.

La sintassi for è:

for (init; condition; increment)
    ...

Il che equivale in qualche modo (ignorando continue e break per ora) equivalente a:

init;
while (condition) {
    ...
    increment;
}

Quindi il tuo esempio for loop è (ignorando ancora continue e break ) equivalente a

p=0;
while (p+=(a&1)*b,a!=1) {
    ...
    a>>=1,b<<=1;
}

Che agisce come se (ignorando di nuovo continue e break ):

p=0; 
while (true) {
    p+=(a&1)*b;
    if (a == 1) break;
    ...
    a>>=1;
    b<<=1;
}

Due dettagli extra del ciclo for che non erano nella conversione semplificata in un ciclo while sopra:

  • Se la condizione viene omessa, è sempre true (risultante in un ciclo infinito a meno che break , goto o qualcos'altro si rompa il ciclo).
  • Un continue si comporta come se fosse un passaggio a un'etichetta appena prima dell'incremento, diversamente da un continua nel ciclo while che salta l'incremento.

Inoltre, un dettaglio importante sull'operatore virgola: è un punto sequenza, come & amp; & amp; e || (motivo per cui posso dividerlo in dichiarazioni separate e mantenerne intatto il significato).


Modifiche in C99

Lo standard C99 introduce un paio di sfumature non menzionate in precedenza in questa spiegazione (che è molto buona per C89 / C90).

Innanzitutto, tutti i loop sono blocchi a sé stanti. In effetti,

for (...) { ... }

è esso stesso avvolto in un paio di parentesi graffe

{
for (...) { ... }
}

Lo standard dice:

  

ISO / IEC 9899: 1999 §6.8.5 Dichiarazioni di iterazione

     

¶5 Un'istruzione di iterazione è un blocco il cui ambito è un sottoinsieme rigoroso del suo ambito   blocco di chiusura. Il corpo del loop è anche un blocco il cui ambito è un sottoinsieme rigoroso dell'ambito   della dichiarazione di iterazione.

Questo è anche descritto nel Razionale in termini di set extra di parentesi graffe.

In secondo luogo, la parte init in C99 può essere una (singola) dichiarazione, come in

for (int i = 0; i < sizeof(something); i++) { ... }

Ora il 'blocco avvolto attorno al loop' si presenta autonomo; spiega perché non è possibile accedere alla variabile i al di fuori del ciclo. Puoi dichiarare più di una variabile, ma devono essere tutte dello stesso tipo:

for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }

Lo standard dice:

  

ISO / IEC 9899: 1999 §6.8.5.3 La dichiarazione for

     

La dichiarazione

for ( clause-1 ; expression-2 ; expression-3 ) statement
     

si comporta come segue: L'espressione expression-2 è l'espressione di controllo che è   valutato prima di ogni esecuzione del corpo del loop. L'espressione expression-3 è   valutato come espressione nulla dopo ogni esecuzione del corpo del loop. Se la clausola-1 è a   dichiarazione, la portata di tutte le variabili che dichiara è il resto della dichiarazione e   l'intero ciclo, comprese le altre due espressioni; viene raggiunto nell'ordine di esecuzione   prima della prima valutazione dell'espressione di controllo. Se la clausola-1 è un'espressione, lo è   valutato come espressione nulla prima della prima valutazione dell'espressione di controllo. 133)

     

Sia la clausola-1 che l'espressione-3 possono essere omesse. Un'espressione-2 omessa è sostituita da a   costante diversa da zero.

     

133) Pertanto, la clausola-1 specifica l'inizializzazione per il ciclo, dichiarando possibilmente una o più variabili da utilizzare in   il cappio; l'espressione di controllo, espressione-2, specifica una valutazione effettuata prima di ogni iterazione,   tale che l'esecuzione del ciclo continua fino a quando l'espressione non è uguale a 0; ed espressione-3   specifica un'operazione (come l'incremento) che viene eseguita dopo ogni iterazione.

Altri suggerimenti

La virgola separa semplicemente due espressioni ed è valida ovunque in C dove è consentita un'espressione normale. Questi vengono eseguiti in ordine da sinistra a destra. Il valore dell'espressione più a destra è il valore dell'espressione complessiva.

I cicli

?? per sono composti da tre parti, ognuna delle quali può anche essere vuota; uno (il primo) viene eseguito all'inizio e uno (il terzo) alla fine di ogni iterazione. Queste parti di solito inizializzano e incrementano un contatore, rispettivamente; ma possono fare qualsiasi cosa.

La seconda parte è un test che viene eseguito all'inizio di ogni esecuzione. Se il test restituisce false , il ciclo viene interrotto. Questo è tutto quello che c'è da fare.

Lo stile C per loop è composto da tre espressioni:

for (initializer; condition; counter) statement_or_statement_block;
  • L'inizializzatore viene eseguito una volta, all'avvio del ciclo.
  • La condizione viene verificata prima di ogni iterazione. Il ciclo dura fintanto che valuta vero.
  • Il contatore viene eseguito una volta dopo ogni iterazione.

Ognuna di queste parti può essere un'espressione valida nella lingua in cui scrivi il loop. Ciò significa che possono essere utilizzate in modo più creativo. Qualunque cosa tu voglia fare prima può entrare nell'inizializzatore, qualsiasi cosa tu voglia fare nel mezzo può andare nella condizione o nel contatore, fino al punto in cui il ciclo non ha più un corpo.

A tale scopo, l'operatore virgola è molto utile. Ti consente di concatenare espressioni per formare un'unica nuova espressione. Il più delle volte viene utilizzato in questo modo in un ciclo for, le altre implicazioni dell'operatore virgola (ad es. Considerazioni sull'assegnazione di valore) svolgono un ruolo minore.

Anche se puoi fare cose intelligenti usando la sintassi in modo creativo, ne rimarrei fino a quando non trovo un davvero un buon motivo per farlo. Giocare a code golf con for loop rende il codice più difficile da leggere e comprendere (e mantenere).

La wikipedia ha anche un bell'articolo sul ciclo for .

Tutto è facoltativo in un ciclo for . Possiamo inizializzare più di una variabile, possiamo controllare più di una condizione, possiamo iterare più di una variabile usando l'operatore virgola.

Il seguente ciclo per ti porterà in un ciclo infinito. Fai attenzione controllando la condizione.

for(;;) 

Konrad ha menzionato il punto chiave che vorrei ripetere: il valore dell'espressione più a destra è il valore dell'espressione complessiva.

Un compilatore Gnu ha dichiarato questo avviso quando ho inserito due test nella condizione "quot". sezione del ciclo for

warning: left-hand operand of comma expression has no effect

Cosa intendevo veramente per la "condizione" sono stati due test con un " & amp; & amp; " fra. Secondo la dichiarazione di Konrad, solo il test sulla destra della virgola influirebbe sulla condizione.

il ciclo for è l'esecuzione per un tempo particolare per (;;)

la sintassi di for loop

for (;;)

o

per (inizializzatore; condizione; contatore)

ad es. (rmv = 1; rmv < = 15; rmv ++)

esecuzione a 15 volte per blocco

1. prima inizializzare il valore perché avvia il valore

(ad esempio) rmv = 1 o rmv = 2

2. seconda istruzione è test la condizione è vera o falsa, la condizione vero no. di esecuzione del ciclo for e la condizione è falsa termina per blocco,

ad es. i = 5; i < = 10 la condizione è vera

i=10;i<10 the condition is false terminate for block,

3.questo è incremento o decremento

(ad esempio) rmv ++ o ++ rmv

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top