web-dev-qa-db-fra.com

Pourquoi est-ce que je reçois "une étiquette ne peut faire partie que d'une déclaration et une déclaration n'est pas une déclaration" si j'ai une variable initialisée après une étiquette?

J'ai le code simplifié suivant:

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

Je reçois une erreur car une nouvelle variable est déclarée après l'étiquette. Si je mets le contenu (principalement l'initialisation) après le libellé dans un bloc {}, la compilation réussit.

Je pense que je comprends la raison du blocage en cas de changement, mais pourquoi devrait-il être applicable en cas de libellé?

Cette erreur provient d'un compilateur gcc

87
user1952500

La norme linguistique ne le permet tout simplement pas. Les étiquettes ne peuvent être suivies que par des instructions, et les déclarations ne comptent pas comme des instructions en C. Le moyen le plus simple de contourner ce problème consiste à insérer une instruction vide après votre étiquette, ce qui vous évite de garder une trace de la portée de la manière dont vous auriez besoin. à l'intérieur d'un bloc.

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

C'est une bizarrerie de la grammaire C. Un étiquette (Cleanup:) n'est pas autorisé à apparaître immédiatement avant une déclaration (telle que char *str ...;), uniquement avant une déclaration (printf(...);). En C89, ce n'était pas une grosse difficulté car declarations ne pouvait apparaître qu'au tout début d'un bloc, vous pouvez donc toujours baisser le libellé un peu et éviter le problème. En C99, vous pouvez mélanger des déclarations et du code, mais vous ne pouvez toujours pas mettre une étiquette immédiatement avant une déclaration.

Vous pouvez mettre un point-virgule immédiatement après le signe deux-points de l'étiquette (comme suggéré par Renan) pour créer une instruction vide; C'est ce que je ferais dans un code généré par une machine. Vous pouvez également hisser la déclaration en haut de la fonction:

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