Warum kann die switch-Anweisung nicht auf Zeichenfolgen angewendet werden?

227

Kompilieren Sie den folgenden Code und erhalten Sie den Fehler von type illegal.

int main()
{
    // Compilation error - switch expression of type illegal
    switch(std::string("raj"))
    {
    case"sda":
    }
}

Sie können keinen String entweder verwenden switchoder case. Warum? Gibt es eine Lösung, die gut funktioniert, um Logik zu unterstützen, die dem Einschalten von Zeichenfolgen ähnelt?

yesraaj
quelle
6
Gibt es eine Boost-Alternative, die die Kartenkonstruktion hinter einem MAKRO verbirgt?
Balki
@balki Ich bin mir nicht sicher, was Boost angeht, aber es ist einfach, solche Makros zu schreiben. Im Falle von Qt können Sie dann die Zuordnung mitQMetaEnum
phuclv

Antworten:

189

Der Grund dafür hat mit dem Typensystem zu tun. C / C ++ unterstützt Zeichenfolgen als Typ nicht wirklich. Es unterstützt zwar die Idee eines konstanten char-Arrays, versteht jedoch den Begriff eines Strings nicht vollständig.

Um den Code für eine switch-Anweisung zu generieren, muss der Compiler verstehen, was es bedeutet, dass zwei Werte gleich sind. Für Elemente wie Ints und Enums ist dies ein trivialer Bitvergleich. Aber wie soll der Compiler 2 String-Werte vergleichen? Groß- und Kleinschreibung beachten, nicht berücksichtigen, kulturbewusst usw. Ohne eine vollständige Kenntnis einer Zeichenfolge kann dies nicht genau beantwortet werden.

Darüber hinaus werden C / C ++ - Switch-Anweisungen normalerweise als Verzweigungstabellen generiert . Es ist bei weitem nicht so einfach, eine Verzweigungstabelle für einen Switch im String-Stil zu generieren.

JaredPar
quelle
11
Das Argument der Verzweigungstabelle sollte nicht zutreffen - dies ist nur ein möglicher Ansatz, der einem Compilerautor zur Verfügung steht. Für einen Produktionscompiler müssen abhängig von der Komplexität des Switches häufig mehrere Ansätze verwendet werden.
Sockel
5
@plinth, ich habe es dort hauptsächlich aus historischen Gründen platziert. Viele der Fragen "Warum macht C / C ++ das?" Können leicht durch den Verlauf des Compilers beantwortet werden. Zu der Zeit, als sie es schrieben, war C eine verherrlichte Versammlung und daher war Switch wirklich eine bequeme Verzweigungstabelle.
JaredPar
113
Ich stimme ab, weil ich nicht verstehe, wie der Compiler 2 Zeichenfolgenwerte in if-Anweisungen vergleichen kann, aber vergesse, wie man in switch-Anweisungen dasselbe macht.
15
Ich denke nicht, dass die ersten beiden Absätze triftige Gründe sind. Besonders seit C ++ 14, als std::stringLiterale hinzugefügt wurden. Es ist meistens historisch. Aber ein Problem , das in den Sinn kommt , ist , dass mit der Art und Weise switchzur Zeit arbeitet, vervielfältigen cases muss zum Zeitpunkt der Kompilierung erkannt werden; Dies ist jedoch für Zeichenfolgen möglicherweise nicht so einfach (unter Berücksichtigung der Auswahl des Laufzeitgebietsschemas usw.). Ich nehme an, dass so etwas constexprFälle erfordern oder nicht spezifiziertes Verhalten hinzufügen müsste (niemals etwas, was wir tun wollen).
MM
8
Es gibt eine klare Definition, wie zwei std::stringWerte oder sogar ein std::stringmit einem const char-Array verglichen werden sollen (nämlich unter Verwendung von operator ==). Es gibt keinen technischen Grund, der den Compiler daran hindern würde, eine switch-Anweisung für einen Typ zu generieren, der diesen Operator bereitstellt. Es würde einige Fragen zu Dingen wie der Lebensdauer der Etiketten aufwerfen, aber alles in allem ist dies in erster Linie eine Entscheidung über das Sprachdesign, keine technische Schwierigkeit.
MikeMB
60

Wie bereits erwähnt, erstellen Compiler gerne Nachschlagetabellen, die switchAnweisungen nach Möglichkeit auf ein Timing nahe O (1) optimieren . Kombinieren Sie dies mit der Tatsache, dass die C ++ - Sprache keinen Zeichenfolgentyp hat - std::stringist Teil der Standardbibliothek, die nicht Teil der Sprache an sich ist.

Ich werde eine Alternative anbieten, die Sie vielleicht in Betracht ziehen möchten. Ich habe sie in der Vergangenheit effektiv eingesetzt. Anstatt die Zeichenfolge selbst umzuschalten, schalten Sie das Ergebnis einer Hash-Funktion um, die die Zeichenfolge als Eingabe verwendet. Ihr Code ist fast so klar wie das Umschalten der Zeichenfolge, wenn Sie einen vorgegebenen Satz von Zeichenfolgen verwenden:

enum string_code {
    eFred,
    eBarney,
    eWilma,
    eBetty,
    ...
};

string_code hashit (std::string const& inString) {
    if (inString == "Fred") return eFred;
    if (inString == "Barney") return eBarney;
    ...
}

void foo() {
    switch (hashit(stringValue)) {
    case eFred:
        ...
    case eBarney:
        ...
    }
}

Es gibt eine Reihe offensichtlicher Optimierungen, die ziemlich genau dem folgen, was der C-Compiler mit einer switch-Anweisung machen würde ... komisch, wie das passiert.

D. Shawley
quelle
15
Das ist wirklich enttäuschend, weil Sie nicht wirklich haschen. Mit modernem C ++ können Sie tatsächlich zur Kompilierungszeit mit einer constexpr-Hash-Funktion hashen. Ihre Lösung sieht sauber aus, hat aber all das Unangenehme, wenn die Leiter leider läuft. Die folgenden Kartenlösungen wären besser und vermeiden auch den Funktionsaufruf. Wenn Sie zwei Karten verwenden, können Sie außerdem Text für die Fehlerprotokollierung einbauen.
Dirk Bester
Sie können die Aufzählung auch mit Lambdas vermeiden: stackoverflow.com/a/42462552/895245
Ciro Santilli 法轮功 冠状 病 六四 事件 17
Könnte Hash eine Constexpr-Funktion sein? Vorausgesetzt, Sie übergeben ein const char * anstelle eines std :: string.
Victor Stone
Aber wieso? Sie können die Ausführung der if-Anweisung immer über einem Switch verwenden. Beide haben nur minimale Auswirkungen, aber die Leistungsvorteile mit einem Switch werden durch die if-else-Suche beseitigt. Nur ein if-else zu verwenden sollte geringfügig schneller, aber vor allem deutlich kürzer sein.
Zoe
20

C ++

constexpr Hash-Funktion:

constexpr unsigned int hash(const char *s, int off = 0) {                        
    return !s[off] ? 5381 : (hash(s, off+1)*33) ^ s[off];                           
}                                                                                

switch( hash(str) ){
case hash("one") : // do something
case hash("two") : // do something
}
Nick
quelle
1
Sie müssen sicherstellen, dass keiner Ihrer Fälle den gleichen Wert hat. Und selbst dann können Fehler auftreten, bei denen andere Zeichenfolgen, die beispielsweise denselben Wert wie Hash ("eins") haben, das erste "Etwas" in Ihrem Switch falsch ausführen.
David Ljung Madison Stellar
Ich weiß, aber wenn es auf den gleichen Wert hasht, wird es nicht kompiliert und Sie werden es rechtzeitig bemerken.
Nick
Guter Punkt - aber das löst nicht die Hash-Kollision für andere Zeichenfolgen, die nicht Teil Ihres Switch sind. In einigen Fällen spielt das vielleicht keine Rolle, aber wenn dies eine generische "Go-to" -Lösung wäre, könnte ich mir vorstellen, dass es sich irgendwann um ein Sicherheitsproblem oder ähnliches handelt.
David Ljung Madison Stellar
7
Sie können ein hinzufügen operator "", um den Code schöner zu machen. constexpr inline unsigned int operator "" _(char const * p, size_t) { return hash(p); }Und benutze es wie case "Peter"_: break; Demo
hare1039
15

C ++ 11 Update von anscheinend nicht @MarmouCorp oben aber http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4067/Switch-on-Strings-in-C.htm

Verwendet zwei Maps zum Konvertieren zwischen den Zeichenfolgen und der Klassenaufzählung (besser als einfache Aufzählung, da die Werte darin enthalten sind, und umgekehrte Suche nach netten Fehlermeldungen).

Die Verwendung von statisch im Codeguru-Code ist mit Compiler-Unterstützung für Initialisierungslisten möglich, was VS 2013 plus bedeutet. gcc 4.8.1 war damit einverstanden, nicht sicher, wie weit hinten es kompatibel sein würde.

/// <summary>
/// Enum for String values we want to switch on
/// </summary>
enum class TestType
{
    SetType,
    GetType
};

/// <summary>
/// Map from strings to enum values
/// </summary>
std::map<std::string, TestType> MnCTest::s_mapStringToTestType =
{
    { "setType", TestType::SetType },
    { "getType", TestType::GetType }
};

/// <summary>
/// Map from enum values to strings
/// </summary>
std::map<TestType, std::string> MnCTest::s_mapTestTypeToString
{
    {TestType::SetType, "setType"}, 
    {TestType::GetType, "getType"}, 
};

...

std::string someString = "setType";
TestType testType = s_mapStringToTestType[someString];
switch (testType)
{
    case TestType::SetType:
        break;

    case TestType::GetType:
        break;

    default:
        LogError("Unknown TestType ", s_mapTestTypeToString[testType]);
}
Dirk Bester
quelle
Ich sollte beachten, dass ich später eine Lösung gefunden habe, die String-Literale und Berechnungen zur Kompilierungszeit erfordert (C ++ 14 oder 17, glaube ich), bei der Sie die Case-Strings zur Kompilierungszeit und die Switch-String zur Laufzeit hashen können. Es würde sich vielleicht für wirklich lange Schalter lohnen, aber sicherlich noch weniger abwärtskompatibel, wenn das wichtig ist.
Dirk Bester
Könnten Sie bitte die Lösung zur Kompilierungszeit hier teilen? Vielen Dank!
qed
12

Das Problem ist, dass die switch-Anweisung in C ++ aus Optimierungsgründen nur für primitive Typen funktioniert und Sie sie nur mit Konstanten für die Kompilierungszeit vergleichen können.

Vermutlich liegt der Grund für die Einschränkung darin, dass der Compiler eine Form der Optimierung anwenden kann, indem er den Code auf einen cmp-Befehl und einen Goto kompiliert, bei dem die Adresse basierend auf dem Wert des Arguments zur Laufzeit berechnet wird. Da Verzweigungen und und Schleifen mit modernen CPUs nicht gut funktionieren, kann dies eine wichtige Optimierung sein.

Um dies zu umgehen, müssen Sie leider auf if-Aussagen zurückgreifen.

Tomjen
quelle
Eine optimierte Version einer switch-Anweisung, die mit Strings arbeiten kann, ist definitiv möglich. Die Tatsache, dass sie nicht denselben Codepfad wiederverwenden können, den sie für primitive Typen verwenden, bedeutet nicht, dass sie nicht std::stringund andere erste Bürger in der Sprache machen und sie in switch-Anweisungen mit einem effizienten Algorithmus unterstützen können.
Ceztko
10

std::map + C ++ 11 Lambdas-Muster ohne Aufzählungen

unordered_mapfür die potenziell amortisierten O(1): Was ist der beste Weg, um eine HashMap in C ++ zu verwenden?

#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

int main() {
    int result;
    const std::unordered_map<std::string,std::function<void()>> m{
        {"one",   [&](){ result = 1; }},
        {"two",   [&](){ result = 2; }},
        {"three", [&](){ result = 3; }},
    };
    const auto end = m.end();
    std::vector<std::string> strings{"one", "two", "three", "foobar"};
    for (const auto& s : strings) {
        auto it = m.find(s);
        if (it != end) {
            it->second();
        } else {
            result = -1;
        }
        std::cout << s << " " << result << std::endl;
    }
}

Ausgabe:

one 1
two 2
three 3
foobar -1

Verwendung innerhalb von Methoden mit static

Um dieses Muster in Klassen effizient zu nutzen, initialisieren Sie die Lambda-Karte statisch, oder Sie zahlen O(n)jedes Mal, wenn Sie sie von Grund auf neu erstellen.

Hier können wir mit der {}Initialisierung einer staticMethodenvariablen durchkommen : Statische Variablen in Klassenmethoden , aber wir könnten auch die Methoden verwenden, die unter: Statische Konstruktoren in C ++? Ich muss private statische Objekte initialisieren

Es war notwendig, die Lambda-Kontexterfassung [&]in ein Argument umzuwandeln , oder das wäre undefiniert gewesen: const static auto lambda, das mit der Erfassung als Referenz verwendet wird

Beispiel, das dieselbe Ausgabe wie oben erzeugt:

#include <functional>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

class RangeSwitch {
public:
    void method(std::string key, int &result) {
        static const std::unordered_map<std::string,std::function<void(int&)>> m{
            {"one",   [](int& result){ result = 1; }},
            {"two",   [](int& result){ result = 2; }},
            {"three", [](int& result){ result = 3; }},
        };
        static const auto end = m.end();
        auto it = m.find(key);
        if (it != end) {
            it->second(result);
        } else {
            result = -1;
        }
    }
};

int main() {
    RangeSwitch rangeSwitch;
    int result;
    std::vector<std::string> strings{"one", "two", "three", "foobar"};
    for (const auto& s : strings) {
        rangeSwitch.method(s, result);
        std::cout << s << " " << result << std::endl;
    }
}
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
3
Beachten Sie, dass zwischen diesem Ansatz und einer switchAussage ein Unterschied besteht . Das Duplizieren von Fallwerten in einer switchAnweisung ist ein Fehler bei der Kompilierung. Bei std::unordered_mapstillschweigender Verwendung werden doppelte Werte akzeptiert.
D.Shawley
6

In C ++ und C funktionieren Switches nur für ganzzahlige Typen. Verwenden Sie stattdessen eine if else-Leiter. C ++ hätte offensichtlich eine Art swich-Anweisung für Strings implementieren können - ich denke, niemand hat es für sinnvoll gehalten, und ich stimme ihnen zu.


quelle
stimmte zu, aber wissen Sie,
warum
Geschichte? Das Einschalten von reellen Zahlen, Zeigern und Strukturen (die einzigen anderen Datentypen von C) macht keinen Sinn, daher beschränkte C sie auf ganze Zahlen.
Besonders wenn Sie Klassen einschalten, die implizite Konvertierungen ermöglichen, werden Sie einmal eine wirklich gute Zeit haben.
Scharfzahn
6

Warum nicht? Sie können die Switch-Implementierung mit äquivalenter Syntax und derselben Semantik verwenden. Die CSprache enthält überhaupt keine Objekte und Zeichenfolgenobjekte, aber Zeichenfolgen in Csind nullterminierte Zeichenfolgen, auf die durch einen Zeiger verwiesen wird. Die C++Sprache hat die Möglichkeit, Überladungsfunktionen für den Objektvergleich oder die Überprüfung der Objektgleichheit zu erstellen. Wie Cso C++ist flexibel genug , um solche Schalter für Strings haben C Sprache und für Objekte jeglicher Art , dass die Unterstützung comparaison oder Scheck Gleichheit für C++Sprache. Und moderne C++11ermöglichen es, diese Switch-Implementierung ausreichend effektiv zu gestalten.

Ihr Code wird folgendermaßen aussehen:

std::string name = "Alice";

std::string gender = "boy";
std::string role;

SWITCH(name)
  CASE("Alice")   FALL
  CASE("Carol")   gender = "girl"; FALL
  CASE("Bob")     FALL
  CASE("Dave")    role   = "participant"; BREAK
  CASE("Mallory") FALL
  CASE("Trudy")   role   = "attacker";    BREAK
  CASE("Peggy")   gender = "girl"; FALL
  CASE("Victor")  role   = "verifier";    BREAK
  DEFAULT         role   = "other";
END

// the role will be: "participant"
// the gender will be: "girl"

Es ist beispielsweise möglich, kompliziertere Typen std::pairsoder beliebige Strukturen oder Klassen zu verwenden, die Gleichheitsoperationen (oder Vergleiche für den Schnellmodus ) unterstützen.

Eigenschaften

  • jede Art von Daten, die Vergleiche oder die Überprüfung der Gleichheit unterstützen
  • Möglichkeit, kaskadierende verschachtelte Switch-Statemens zu erstellen.
  • Möglichkeit, Fallaussagen zu durchbrechen oder zu durchbrechen
  • Möglichkeit, nicht konstante Fallausdrücke zu verwenden
  • möglich, um den schnellen statischen / dynamischen Modus mit Baumsuche zu aktivieren (für C ++ 11)

Sintax Unterschiede mit Sprachwechsel ist

  • Schlüsselwörter in Großbuchstaben
  • benötigen Klammern für die CASE-Anweisung
  • Semikolon ';' am Ende von Anweisungen ist nicht erlaubt
  • Doppelpunkt ':' bei CASE-Anweisung ist nicht zulässig
  • Benötigen Sie eines der Schlüsselwörter BREAK oder FALL am Ende der CASE-Anweisung

Für die verwendete C++97Sprache lineare Suche. Für C++11und moderner möglich, quickModus wuth Baumsuche zu verwenden, wo return Anweisung in CASE nicht erlaubt wird. Die CSprachimplementierung ist vorhanden, wenn char*Typ- und nullterminierte Zeichenfolgenvergleiche verwendet werden.

Lesen Sie mehr über diese Switch-Implementierung.

oklas
quelle
6

Um eine Variation mit dem einfachsten möglichen Container hinzuzufügen (keine geordnete Karte erforderlich) ... Ich würde mich nicht um eine Aufzählung kümmern - setzen Sie einfach die Containerdefinition unmittelbar vor den Schalter, damit Sie leicht erkennen können, welche Zahl steht Welcher Fall.

Dies führt eine Hash-Suche in der unordered_mapund verwendet die zugehörige int, um die switch-Anweisung zu steuern. Sollte ziemlich schnell sein. Beachten Sie, dass atanstelle von verwendet wird [], da ich diesen Container gemacht habe const. Die Verwendung []kann gefährlich sein. Wenn sich die Zeichenfolge nicht in der Karte befindet, erstellen Sie eine neue Zuordnung und erhalten möglicherweise undefinierte Ergebnisse oder eine kontinuierlich wachsende Karte.

Beachten Sie, dass die at()Funktion eine Ausnahme auslöst, wenn sich die Zeichenfolge nicht in der Karte befindet. Vielleicht möchten Sie zuerst mit testen count().

const static std::unordered_map<std::string,int> string_to_case{
   {"raj",1},
   {"ben",2}
};
switch(string_to_case.at("raj")) {
  case 1: // this is the "raj" case
       break;
  case 2: // this is the "ben" case
       break;


}

Die Version mit einem Test für eine undefinierte Zeichenfolge folgt:

const static std::unordered_map<std::string,int> string_to_case{
   {"raj",1},
   {"ben",2}
};
// in C++20, you can replace .count with .contains
switch(string_to_case.count("raj") ? string_to_case.at("raj") : 0) {
  case 1: // this is the "raj" case
       break;
  case 2: // this is the "ben" case
       break;
  case 0: //this is for the undefined case

}
rsjaffe
quelle
4

Ich denke, der Grund dafür ist, dass in C-Strings keine primitiven Typen sind, wie Tomjen sagte, denken Sie in einem String als char-Array, so dass Sie Dinge wie:

switch (char[]) { // ...
switch (int[]) { // ...
grilix
quelle
3
Ohne nachzuschlagen, würde ein Zeichenarray wahrscheinlich zu einem char * degenerieren, das direkt in einen integralen Typ konvertiert wird. Es könnte also gut kompiliert werden, aber es wird sicherlich nicht das tun, was Sie wollen.
David Thornley
3

In C ++ sind Strings keine erstklassigen Bürger. Die Zeichenfolgenoperationen werden über die Standardbibliothek ausgeführt. Ich denke, das ist der Grund. Außerdem verwendet C ++ die Optimierung von Verzweigungstabellen, um die switch case-Anweisungen zu optimieren. Schauen Sie sich den Link an.

http://en.wikipedia.org/wiki/Switch_statement

Chappar
quelle
2

In C ++ können Sie nur eine switch-Anweisung für int und char verwenden

CodeMonkey1313
quelle
3
Ein Zeichen wird auch zu einem int.
Strager
Zeiger können auch. Das bedeutet, dass Sie manchmal etwas kompilieren können, das in einer anderen Sprache Sinn macht, aber nicht richtig läuft.
David Thornley
Sie können tatsächlich longund verwenden long long, was sich nicht in verwandeln wird int. Dort besteht keine Gefahr der Kürzung.
MSalters
0
    cout << "\nEnter word to select your choice\n"; 
    cout << "ex to exit program (0)\n";     
    cout << "m     to set month(1)\n";
    cout << "y     to set year(2)\n";
    cout << "rm     to return the month(4)\n";
    cout << "ry     to return year(5)\n";
    cout << "pc     to print the calendar for a month(6)\n";
    cout << "fdc      to print the first day of the month(1)\n";
    cin >> c;
    cout << endl;
    a = c.compare("ex") ?c.compare("m") ?c.compare("y") ? c.compare("rm")?c.compare("ry") ? c.compare("pc") ? c.compare("fdc") ? 7 : 6 :  5  : 4 : 3 : 2 : 1 : 0;
    switch (a)
    {
        case 0:
            return 1;

        case 1:                   ///m
        {
            cout << "enter month\n";
            cin >> c;
            cout << endl;
            myCalendar.setMonth(c);
            break;
        }
        case 2:
            cout << "Enter year(yyyy)\n";
            cin >> y;
            cout << endl;
            myCalendar.setYear(y);
            break;
        case 3:
             myCalendar.getMonth();
            break;
        case 4:
            myCalendar.getYear();
        case 5:
            cout << "Enter month and year\n";
            cin >> c >> y;
            cout << endl;
            myCalendar.almanaq(c,y);
            break;
        case 6:
            break;

    }
Juan Llanes
quelle
4
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Benjamin W.
0

In vielen Fällen können Sie zusätzliche Arbeit vermeiden, indem Sie das erste Zeichen aus der Zeichenfolge ziehen und einschalten. Möglicherweise müssen Sie charat (1) verschachteln, wenn Ihre Fälle mit demselben Wert beginnen. Jeder, der Ihren Code liest, würde sich über einen Hinweis freuen, da die meisten nur if-else-if prüfen würden

Marshall Taylor
quelle
0

Weitere funktionale Problemumgehung für das Switch-Problem:

class APIHandlerImpl
{

// define map of "cases"
std::map<string, std::function<void(server*, websocketpp::connection_hdl, string)>> in_events;

public:
    APIHandlerImpl()
    {
        // bind handler method in constructor
        in_events["/hello"] = std::bind(&APIHandlerImpl::handleHello, this, _1, _2, _3);
        in_events["/bye"] = std::bind(&APIHandlerImpl::handleBye, this, _1, _2, _3);
    }

    void onEvent(string event = "/hello", string data = "{}")
    {
        // execute event based on incomming event
        in_events[event](s, hdl, data);
    }

    void APIHandlerImpl::handleHello(server* s, websocketpp::connection_hdl hdl, string data)
    {
        // ...
    }

    void APIHandlerImpl::handleBye(server* s, websocketpp::connection_hdl hdl, string data)
    {
        // ...
    }
}
FelikZ
quelle
-1

Sie können keine Zeichenfolge in Switch-Groß- und Kleinschreibung verwenden. Es sind nur int & char zulässig. Stattdessen können Sie versuchen, die Zeichenfolge mit enum darzustellen und im switch case-Block wie zu verwenden

enum MyString(raj,taj,aaj);

Verwenden Sie es in der swich case-Anweisung.

anil
quelle
-1

Schalter funktionieren nur mit integralen Typen (int, char, bool usw.). Warum nicht eine Karte verwenden, um eine Zeichenfolge mit einer Nummer zu koppeln, und diese Nummer dann mit dem Schalter verwenden?

derpface
quelle
-2

Das liegt daran, dass C ++ Schalter in Sprungtabellen verwandelt. Es führt eine triviale Operation an den Eingabedaten durch und springt zur richtigen Adresse, ohne sie zu vergleichen. Da eine Zeichenfolge keine Zahl, sondern ein Array von Zahlen ist, kann C ++ keine Sprungtabelle daraus erstellen.

movf    INDEX,W     ; move the index value into the W (working) register from memory
addwf   PCL,F       ; add it to the program counter. each PIC instruction is one byte
                    ; so there is no need to perform any multiplication. 
                    ; Most architectures will transform the index in some way before 
                    ; adding it to the program counter

table                   ; the branch table begins here with this label
    goto    index_zero  ; each of these goto instructions is an unconditional branch
    goto    index_one   ; of code
    goto    index_two
    goto    index_three

index_zero
    ; code is added here to perform whatever action is required when INDEX = zero
    return

index_one
...

(Code aus Wikipedia https://en.wikipedia.org/wiki/Branch_table )

Jean-Luc Nacif Coelho
quelle
4
C ++ erfordert keine bestimmte Implementierung seiner Syntax. Eine naive cmp/ jccImplementierung kann nach dem C ++ Standard genauso gültig sein.
Ruslan