2014-10-22 16 views
5

Sono di linguaggi OOP di alto livello C# e Java e recentemente ho iniziato a grattarmi la testa in C. Sento che C sia un po 'strano quanto lo si percepisce con JS. Così da chiarire sotto:Perché questo uso della virgola funziona in un'espressione ma fallisce in una dichiarazione?

sottostante riporta l'errore e che sembra intuitivo come sembra sintassi non corretta anche in lingue OOP

int i=0,1,2; 

/* 
Error : expected identifier or ‘(’ before numeric constant 
int i = 0, 1, 2; 
      ^
*/ 

Tuttavia seguito funziona sorprendentemente:

int i; 
i = 0,1,2; //works 

Perché questo comportamento ? Il loro significato è quello di mantenere un simile comportamento o solo qualche parsing tecnico?

+4

@ Mahesha999 in realtà la domanda _bigger_ sarebbe: perché mai è necessario scrivere qualcosa del genere? La grammatica dice _ "dichiarazione \ dichiarazione-specificatori; \ dichiarazione-specificatori init-dichiaratore-lista;" _, questo è tutto. Cosa pensi che sia intuitivo (se c'è qualcosa di _intuitivo_ nell'operatore virgola) per scrivere tale codice? –

+0

@DebasishJana questo non spiega perché il caso di dichiarazione non funziona come spiego nella mia risposta che nessun altro sembra aver ottenuto neanche. –

+0

@AdrianoRepetti la distinzione tra ',' in un'espressione e in una dichiarazione sembra essersi persa nelle risposte qui per quale motivo ho aggiunto una risposta. Questa è la parte interessante della domanda. –

risposta

7

Questa è in realtà una domanda complicata perché si basa sui dettagli della grammatica C che è complicata. La migliore fonte per capirlo è lo draft standard, possiamo usare Annex ASommario della sintassi della lingua come riferimento.

L'idea di base è che:

int i=0,1,2; 

è una dichiarazione e:

i = 0,1,2; 

è un'espressione.

In un'espressione possiamo avere la comma operator che valuta la sinistra (di solito per gli effetti collaterali), getta via il risultato e poi valuta il lato destro ecc ...

Nella dichiarazione la virgola è un separatore grammaticale non l'operatore virgola. Il , separa dichiaratori e dal 1 e 2 non sono dichiaratori nel contesto di una dichiarazione questa è la sintassi corretta:

int i=0,1,2; 
     ^^^^ 

La grammatica rilevante dallo standard C99 è la seguente:

init-declarator-list: 
    init-declarator 
    init-declarator-list , init-declarator <--- here comma is just a seperator 
init-declarator: 
    declarator 
    declarator = initializer 

Quindi, in In questo caso, inizializza, che può essere un dichiaratore o un dichiarator = inizializzatore12 sono dichiaratori e quindi abbiamo una sintassi errata.

Vale la pena di nulla che un inizializzatore può essere un incarico espressione, ma questa espressione non ci dà un percorso di una nuda virgola operatore, anche se potremmo finire con un operatore virgola in () (attraverso l'espressione primaria) ma questo non apparirebbe come un separatore.

Per l'espressione della grammatica pertinente sezione 6.5.17 è:

expression: 
    assignment-expression 
    expression , assignment-expression 

e la descrizione dell'operatore virgola è la seguente:

L'operando sinistro dell'operatore virgola viene valutata come vuoto espressione; c'è un punto di sequenza dopo la sua valutazione. Quindi viene valutato l'operando destro ; il risultato ha il suo tipo e valore [...]

Rilevando che l'operatore virgola ha il lowest precedence la seguente espressione:.

i = 0,1,2; 

è equivalente a:

(i = 0),1,2; 

e quindi i otterrà il valore di 0 e i risultati delle ulteriori valutazioni verranno gettati.

+0

+1 Non riesco ancora a vedere il punto della domanda, ma di sicuro questa risposta spiega le ragioni dietro a ciò. –

+0

@AdrianoRepetti da quello che ho capito l'OP sta cercando di capire perché quello che sembra la stessa sintassi non funziona in quelli che sembrano contesti simili. Se ti soffermi intorno a C o C++ abbastanza a lungo, troverai molte di queste stranezze che non hanno risposte ovvie. –

+0

Sì, ma ... per me questa volta non sembrava così strano! Comunque ... –

9
i = 0,1,2; 

Questo è assegnazione, che è equivalente a:

(i = 0), 1, 2; 

L'operatore virgola (che ha la priorità più bassa) valuta tutti gli operandi da sinistra a destra, prima l'assegnazione i = 0, allora l'espressione 1 e 2 e getta via il risultato.

Il secondo esempio

int i=0,1,2; 

è inizializzazione. Confrontalo con l'inizializzazione legale int i = 0, j = 0;.

Funziona se si utilizza:

int i=(0,1,2); 
+1

e funziona con assegnazione !!! ma perché??? quali sono le specifiche esatte dietro cui sarà consentita la virgola o che cosa è permesso e non consentito con assegnazione e inizializzazione? – Mahesha999

+0

quello che fa di fatto è assegnare a 'i' il risultato di' (0,1,2) ', che è, come' operatore, (operatore, (0,1), 2) ' – qdii

+0

@qdii, sbagliato, fa '(i = 0), 1, 2'. – zch

0

1.

int i, j; 
    i = 3,0,1,2; 
    printf("%d\n", i); => prints 3 

2.

i = 3,j =7; 
    printf("%d, %d\n", i, j); => prints 3 and 7 

i = 3,0,1,2; Questo assegna 3 to i, quindi esegue 0, 1 and 2. Controlla il 2 ° esempio che ho citato.

Inoltre, provare i=3;0;1;2; Questo non segnalerà alcun errore. Eseguirà solo (i=3), (0), (1) and (2).