208 votes

Une syntaxe valide, mais sans valeur en cas de coupure?

À travers une petite faute de frappe, j'ai accidentellement trouvé cette construction:

 int main(void) {
    char foo = 'c';

    switch(foo)
    {
        printf("Cant Touch This\n");   // This line is Unreachable

        case 'a': printf("A\n"); break;
        case 'b': printf("B\n"); break;
        case 'c': printf("C\n"); break;
        case 'd': printf("D\n"); break;
    }

    return 0;
}
 

Il semble que le printf au sommet de la déclaration switch est valide, mais aussi complètement inaccessible.

J'ai une compilation propre, sans même un avertissement sur le code inaccessible, mais cela semble inutile.

Un compilateur doit-il signaler ceci comme un code inaccessible?
Est-ce que cela sert à quelque chose?

226voto

AlexD Points 7089

Peut-être pas le plus utile, mais pas complètement inutile. Vous pouvez l'utiliser pour déclarer une variable locale disponible dans switch de la portée.

switch (foo)
{
    int i;
case 0:
    i = 0;
    //....
case 1:
    i = 1;
    //....
}

La norme (N1579 6.8.4.2/7) a l'exemple suivant:

EXEMPLE Dans l'artificiel fragment d'un programme

switch (expr)
{
    int i = 4;
    f(i);
case 0:
    i = 17;
    /* falls through into default code */
default:
    printf("%d\n", i);
}

l'objet dont l'identifiant est i existe automatique de la durée de stockage (dans le bloc), mais n'est jamais initialisé, et donc si le contrôle de l'expression a une valeur différente de zéro, l'appel à l' printf fonction accéder à une valeur indéterminée. De même, l'appel à la fonction f ne peut être atteint.

P. S. BTW, l'échantillon n'est pas valide, le code C++. Dans ce cas (N4140 6.7/3, c'est moi qui souligne):

Un programme qui sautsde 90 à partir d'un point où une variable automatique de la durée de stockage n'est pas dans le champ d'application à un point où il est dans la portée est mal formé , à moins que la variable est de type scalaire, le type de classe avec un trivial par défaut constructeur et d'un trivial destructeur, un cv qualifiés version de l'un de ces types, ou un tableau de l'un des types précédents et est déclarée sans un initialiseur (8.5).


90) Le transfert à partir de la condition d' switch déclaration d'un cas étiquette est considéré comme un saut à cet égard.

Remplacer int i = 4; avec int i; le rend valide en C++.

39voto

Yakk Points 31636

Il est un célèbre l'utilisation de ce qui est appelé Duff de l'Appareil.

int n = (count+3)/4;
switch (count % 4) {
  do {
    case 0: *to = *from++;
    case 3: *to = *from++;
    case 2: *to = *from++;
    case 1: *to = *from++;
  } while (--n > 0);
}

Ici, nous avons la copie d'un tampon pointé par from dans un tampon pointé par to. Nous copions count des instances de données.

L' do{}while() déclaration commence avant la première case de l'étiquette, et l' case étiquettes sont intégrés au sein de l' do{}while().

Cela réduit le nombre de branches conditionnelles à la fin de l' do{}while() boucle rencontrées par à peu près un facteur de 4 (dans cet exemple, la constante peut être modifié à n'importe quelle valeur que vous voulez).

Maintenant, les optimiseurs peut parfois le faire pour vous (surtout si elles sont l'optimisation de streaming/vectorisé instructions), mais sans profil guidée d'optimisation ils ne peuvent pas savoir si vous vous attendez à ce que la boucle soit gros ou pas.

En général, les déclarations de variables peut se produire là-bas et être utilisé dans tous les cas, mais hors de portée après le passage se termine. (note de toute l'initialisation est ignorée)

En outre, le contrôle de flux qui n'est pas le commutateur spécifique peut vous rendre dans cette section du bloc de commutateurs, comme illustré ci-dessus, ou avec un goto.

15voto

16tons Points 562

En supposant que vous utilisiez gcc sous Linux, cela vous aurait donné un avertissement si vous utilisiez la version 4.4 ou une version antérieure.

L'option -Wunreachable-code a été supprimée à partir de gcc 4.4 .

11voto

Sanchke Dellowar Points 1810

Non seulement pour la déclaration de variable, mais aussi pour le saut avancé. Vous pouvez bien l'utiliser si et seulement si vous n'êtes pas enclin au code spaghetti.

 int main()
{
    int i = 1;
    switch(i)
    {
        nocase:
        printf("no case\n");

        case 0: printf("0\n"); break;
        case 1: printf("1\n"); goto nocase;
    }
    return 0;
}
 

Impressions

 1
no case
0 /* Notice how "0" prints even though i = 1 */
 

Il convient de noter que le commutateur est l’une des clauses de flux de contrôle les plus rapides. Il doit donc être très flexible pour le programmeur, ce qui implique parfois des cas comme celui-ci.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X