2013-05-31 23 views
20

Mi sono imbattuto in questo pezzo di codice. Generalmente uso '& &' o '||' per separare più condizioni in un ciclo for, ma questo codice utilizza le virgole per farlo.Condizioni multiple in un ciclo C 'per "

Sorprendentemente, se cambio l'ordine delle condizioni l'uscita varia.

#include<stdio.h> 

int main() { 
    int i, j=2; 

    for(i=0; j>=0,i<=5; i++) 
    { 
     printf("%d ", i+j); 
     j--; 
    } 
    return 0; 
} 

uscita = 2 2 2 2 2 2

#include<stdio.h> 

int main(){ 
    int i, j=2; 

    for(i=0; i<=5,j>=0; i++) 
    { 
     printf("%d ", i+j); 
     j--; 
    } 
    return 0; 
} 

uscita = 2 2 2

Qualcuno può spiegare il motivo? Sembra che stia controllando solo l'ultima condizione separata da virgole.

+2

Codice errato. Hai ragione; più condizioni dovrebbero essere unite con && or ||. – Caleb

+7

Cinque risposte, tutti prendono la domanda eccessivamente alla lettera e spiegano cosa fa una virgola, e non una singola risposta che suggerisce che questo è orribilmente, orribilmente rotto. –

risposta

41

L'operatore virgola valuta tutti i suoi operandi e restituisce il valore dell'ultimo. Quindi, in pratica, qualunque sia la condizione in cui scrivi per prima, verrà ignorata, e il secondo sarà significativo solo.

for (i = 0; j >= 0, i <= 5; i++) 

è quindi equivalente con

for (i = 0; i <= 5; i++) 

che può o non può essere quello che l'autore del codice previsto, a seconda delle sue intenzioni - spero che questo non è il codice di produzione, perché se il programmatore che ha scritto questo voleva esprimere una relazione AND tra le condizioni, quindi questo non è corretto e l'operatore && avrebbe dovuto essere utilizzato.

+1

Il punto importante qui è che il codice in questione non è corretto. – Caleb

+0

@Caleb In che senso? Penso di ottenere quello che stai cercando di suggerire, non sono sicuro che possa o debba essere incluso nella risposta così com'è. –

+0

Questo * non può * essere ciò che l'autore ha inteso, in quanto privo di significato. Non mi fiderei di alcun codice di questo autore. –

5

L'espressione virgola assume il valore di ultima espressione (ad esempio più a destra).

Quindi nel primo ciclo, l'unica espressione di controllo è i<=5; e j>=0 viene ignorato.

Nel secondo ciclo, j>=0 controlla il ciclo e i<=5 viene ignorato.


Come per un motivo ... non c'è motivo. Questo codice è solo errato. La prima parte delle espressioni di virgola non fa niente tranne che confonde i programmatori. Se un programmatore serio ha scritto questo, dovrebbero vergognarsi di se stessi e farsi revocare la propria tastiera.

2

C'è un operatore in C chiamato operatore virgola. Esegue ogni espressione in ordine e restituisce il valore dell'ultima istruzione. È anche un sequence point, il che significa che ogni espressione è garantita per essere eseguita completamente e in ordine prima dell'esecuzione dell'espressione successiva nella serie, simile a && o ||.

+0

Il che rende inutile in questo caso - il primo controllo di condizione non fa nulla di utile. – Caleb

+0

@EricPostpischil Mi scusi, espressione. Sheesh. –

3

Wikipedia dice cosa operatore virgola fa:

"Negli ++ linguaggi di programmazione C e C, l'operatore virgola (rappresentato dal token ,) è un operatore binario che valuta il suo primo operando e scarta il risultato, e poi valuta il secondo operando e restituisce questo valore (e digita)."

+0

-1 La citazione da Wikipedia non risponde alla domanda, che non è ciò che fa la virgola, ma piuttosto perché viene utilizzata qui. – Caleb

+1

@Caleb, sinceramente non credo che la domanda si chieda perché. Perché dice: "Sorprendentemente, se cambio l'ordine delle condizioni l'output varia". Quindi citando risponde. – tafa

3

Non utilizzare questo codice, chi lo ha scritto ha chiaramente una fondamentale incomprensione del linguaggio e non è degno di fiducia l'espressione:.

j >= 0, i <= 5 

valuta le 'j> = 0', poi getta via e non fa nulla con esso, quindi valuta "i < = 5" e lo utilizza, e solo quello, come condizione per terminare il ciclo.L'operatore virgola può essere utilizzato in modo significativo in una condizione di ciclo quando l'operando di sinistra ha effetti collaterali ; vedrai spesso cose come:

for (i = 0, j = 0; i < 10; ++i, ++j) . . . 

in cui la virgola viene utilizzata per intrufolarsi in ulteriori dichiarazioni di inizializzazione e incremento. Ma il codice mostrato non lo sta facendo, o qualsiasi altra cosa significativa.

4

Naturalmente è giusto quello che dici all'inizio, e C logical operator&& e || sono ciò che di solito si usa per "collegare" condizioni (espressioni che possono essere valutate come vere o false); l'operatore virgola non è un operatore logico e il suo uso in quell'esempio non ha senso, come spiegato da altri utenti. Puoi usarlo, ad es. per "concatenare" affermazioni nel per sé: è possibile inizializzare e aggiornare j complessivamente con i; o utilizzare l'operatore virgola nel otherways

#include <stdio.h> 

int main(void) // as std wants 
{ 
    int i, j; 

    // init both i and j; condition, we suppose && is the "original" 
    // intention; update i and j 
    for(i=0, j=2; j>=0 && i<=5; i++, j--) 
    { 
     printf("%d ", i+j); 
    } 
    return 0;   
} 
0

Completano la risposta di Mr. Crocker, stare attenti a ++ o - operatori o non so forse altri operatori. Possono influenzare il ciclo. per esempio ho visto un codice simile a questo in un corso:

for(int i=0; i++*i<-1, i<3; printf(" %d", i)); 

Il risultato sarebbe $ 1 2 $. Quindi la prima affermazione ha influenzato il ciclo mentre il risultato del seguente è un sacco di zeri.

for(int i=0; i<3; printf(" %d", i));