2013-08-28 6 views
65

Ho il seguente codice semplificato:Perché ottengo "un'etichetta può essere solo parte di un'istruzione e una dichiarazione non è un'istruzione" se ho una variabile inizializzata dopo un'etichetta?

#include <stdio.h> 
int main() 
{ 
    printf("Hello "); 
    goto Cleanup; 
Cleanup: 
    char *str = "World\n"; 
    printf("%s\n", str); 
} 

ottengo un errore a causa di una nuova variabile viene dichiarata dopo l'etichetta. Se inserisco il contenuto (principalmente l'inizializzazione) dopo l'etichetta in un blocco {}, la compilazione ha esito positivo.

Penso di aver compreso il motivo del blocco in caso di un interruttore, ma perché dovrebbe essere applicabile in caso di un'etichetta?

Questo errore da un compilatore gcc

+0

Quando si definisce una variabile sotto un'etichetta, è necessario indicare l'ambito della variabile. '' ' #include int main() { printf (" Ciao "); goto Cleanup; Pulizia: { char * str = "Mondo \ n"; printf ("% s \ n", str); } } '' ' –

risposta

86

Lo standard di lingua semplicemente non lo consente. Le etichette possono essere seguite solo da dichiarazioni e le dichiarazioni non contano come dichiarazioni in C. Il modo più semplice per aggirare questo è inserire un'istruzione vuota dopo l'etichetta, che ti solleva dal tenere traccia dell'ambito nel modo in cui avresti bisogno di all'interno di un blocco.

#include <stdio.h> 
int main() 
{ 
    printf("Hello "); 
    goto Cleanup; 
Cleanup: ; //This is an empty statement. 
    char *str = "World\n"; 
    printf("%s\n", str); 
} 
+9

Wow, questo è bizzarro. Qual è la ragione dietro a questo? – user1952500

+20

Prima di C99, tutte le dichiarazioni dovevano precedere tutte le istruzioni all'interno di un blocco, quindi non avrebbe avuto senso avere un'etichetta su una dichiarazione. C99 ha attenuato questa restrizione, consentendo di mescolare dichiarazioni e istruzioni all'interno di un blocco, ma la sintassi di una * istruzione con etichetta * non è stata modificata. –

+3

In genere non è possibile fornire * motivi * per questo tipo di stranezza linguistica. La grammatica è così com'è. Posso dare un'occhiata al documento C Rationale ... non fino a domani, però ... ma probabilmente non troverò nulla. – zwol

17

Questo è un capriccio della grammatica C. Un etichetta (Cleanup:) non è permesso di apparire immediatamente prima di un dichiarazione (come char *str ...;), solo prima una dichiarazione (printf(...);). In C89 questa non è stata una grande difficoltà perché le dichiarazioni potevano apparire solo all'inizio di un blocco, quindi puoi sempre spostare l'etichetta un po 'in basso ed evitare il problema. In C99 puoi mescolare dichiarazioni e codice, ma non puoi ancora mettere un'etichetta immediatamente prima di una dichiarazione.

È possibile inserire un punto e virgola immediatamente dopo i due punti dell'etichetta (come suggerito da Renan) per fare in modo che sia presente un'istruzione vuota; questo è quello che farei nel codice generato dalla macchina. In alternativa, sollevare la dichiarazione all'inizio della funzione:

int main (void) 
{ 
    char *str; 
    printf("Hello "); 
    goto Cleanup; 
Cleanup: 
    str = "World\n"; 
    printf("%s\n", str); 
    return 0; 
} 
Problemi correlati