Partager via


Instruction switch (C++)

Autorise la sélection parmi plusieurs sections de code, selon la valeur d'une expression intégrale.

Syntaxe

selection-statement:
switch(init-statementoptC++17condition)statement

init-statement:
expression-statement
simple-declaration

condition:
expression
attribute-specifier-seqopt decl-specifier-seq declarator brace-or-equal-initializer

labeled-statement:
case constant-expression : statement
default : statement

Notes

Une instruction switch entraîne le transfert du contrôle à une labeled-statement dans son corps d’instruction, en fonction de la valeur de condition.

La condition doit avoir un type intégral, ou être un type de classe qui a une conversion non ambiguë en type intégral. La promotion intégrale a lieu comme décrit dans Conversions standard.

Le corps de l’instruction switch consiste en une série d’étiquettes case et une étiquette optionnelle default. labeled-statement est une de ces étiquettes et les instructions qui suivent. Les instructions étiquetées ne sont pas des exigences syntaxiques mais sans elles, l’instruction switch n’a pas de sens. Deux valeurs constant-expression dans les instructions case ne peuvent pas s’évaluer à la même valeur. L’étiquette default ne peut apparaître qu’une seule fois. L’instruction default est souvent placée à la fin, mais elle peut apparaître n’importe où dans le corps de l’instruction switch. Une étiquette case ou default ne peut apparaître qu’à l’intérieur d’une instruction switch.

La constant-expression dans chaque étiquette de case est convertie en une valeur de constante qui est du même type que condition. Ensuite, elle est comparée à condition pour l’égalité. Le contrôle passe à la première instruction après la valeur case constant-expression qui correspond à la valeur de condition. Le comportement résultant est indiqué dans le tableau suivant.

Comportement de l’instruction switch

Condition Action
La valeur convertie correspond à celle de l'expression de contrôle promue. Le contrôle est transféré à l'instruction qui suit cette étiquette.
Aucune des constantes ne correspond aux constantes des étiquettes case ; une étiquette default est présente. Le contrôle est transféré à l’étiquette default.
Aucune des constantes ne correspond aux constantes des étiquettes case ; aucune étiquette default n’est présente. Le contrôle est transféré à l’instruction qui suit l’instruction switch.

Si une expression correspondante est trouvée, l’exécution peut continuer avec des étiquettes case ou default qui suivent. L’instruction break est utilisée pour arrêter l’exécution et transférer le contrôle à l’instruction qui se trouve après l’instruction switch. En l’absence d’une instruction break, chaque instruction, depuis l’étiquette case correspondante jusqu’à la fin de l’instruction switch, y compris default, est exécutée. Par exemple :

// switch_statement1.cpp
#include <stdio.h>

int main() {
   const char *buffer = "Any character stream";
   int uppercase_A, lowercase_a, other;
   char c;
   uppercase_A = lowercase_a = other = 0;

   while ( c = *buffer++ )   // Walks buffer until NULL
   {
      switch ( c )
      {
         case 'A':
            uppercase_A++;
            break;
         case 'a':
            lowercase_a++;
            break;
         default:
            other++;
      }
   }
   printf_s( "\nUppercase A: %d\nLowercase a: %d\nTotal: %d\n",
      uppercase_A, lowercase_a, (uppercase_A + lowercase_a + other) );
}

Dans l'exemple ci-dessus, uppercase_A est incrémenté si c est un 'A' majuscule. L’instruction break après uppercase_A++ arrête l’exécution du corps de l’instruction switch et le contrôle passe à la boucle while. Sans l’instruction break, l’exécution passerait à l’instruction étiquetée suivante afin que lowercase_a et other soient également incrémentés. Un objectif similaire est réalisé par l’instruction break pour case 'a'. Si c est une minuscule 'a', lowercase_a est incrémenté et l’instruction break termine le corps de l’instruction switch . Si c n’est pas un 'a' ou un 'A', l’instruction default est exécutée.

Visual Studio 2017 et ultérieur (disponible en mode /std:c++17 et ultérieur) : l’attribut [[fallthrough]] est spécifié dans le standard C++17. Vous pouvez l’utiliser dans une instruction switch. C’est un indicateur pour le compilateur ou pour toute personne lisant le code, ce comportement de fourre-tout est intentionnel. Actuellement, le compilateur Microsoft C++ ne produit pas d’avertissement pour le comportement de fourre-tout : cet attribut n’a donc pas d’ effet sur le comportement du compilateur. Dans l’exemple, l’attribut est appliqué à une instruction vide dans l’instruction étiquetée non terminée. En d’autres termes, le point-virgule est nécessaire.

int main()
{
    int n = 5;
    switch (n)
    {

    case 1:
        a();
        break;
    case 2:
        b();
        d();
        [[fallthrough]]; // I meant to do this!
    case 3:
        c();
        break;
    default:
        d();
        break;
    }

    return 0;
}

Visual Studio 2017 version 15.3 et ultérieure (disponible en mode /std:c++17 et ultérieur) : une instruction switch peut avoir une clause init-statement qui se termine par un point-virgule. Elle introduit et initialise une variable dont l’étendue est limitée au bloc de l’instruction switch :

    switch (Gadget gadget(args); auto s = gadget.get_status())
    {
    case status::good:
        gadget.zip();
        break;
    case status::bad:
        throw BadGadget();
    }

Un bloc interne d’une instruction switch peut contenir des définitions avec des initialiseurs dès lors qu’ils sont accessibles, c’est-à-dire non contournés par tous les chemins d’exécution possibles. Les noms présentés à l'aide de ces déclarations ont une portée locale. Par exemple :

// switch_statement2.cpp
// C2360 expected
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
    switch( tolower( *argv[1] ) )
    {
        // Error. Unreachable declaration.
        char szChEntered[] = "Character entered was: ";

    case 'a' :
        {
        // Declaration of szChEntered OK. Local scope.
        char szChEntered[] = "Character entered was: ";
        cout << szChEntered << "a\n";
        }
        break;

    case 'b' :
        // Value of szChEntered undefined.
        cout << szChEntered << "b\n";
        break;

    default:
        // Value of szChEntered undefined.
        cout << szChEntered << "neither a nor b\n";
        break;
    }
}

Une instruction switch peut être imbriquée. Dans ce cas, les étiquettes case ou default s’associent à l’instruction switch la plus proche autour d’elles.

Comportement spécifique à Microsoft

Microsoft C++ ne limite pas le nombre de valeurs case dans une instruction switch. Le nombre est limité uniquement par la mémoire disponible.

Voir aussi

Instructions de sélection
Mots clés