2016-07-06 13 views
6

zu verwenden Ich verwende derzeit statische Const in meinem Code anstelle von "magische Zahlen" wie in "static const" vs "#define" vs "enum" erwähnt.Was anstelle von magischen Zahlen in C

void checkInvalidResponse (uint8_t response) 
{ 
    static const uint8_t INVALID_RESP = 0xFF; 

    if (response == INVALID_RESP) 
    { 
     /* Code for invalid response */ 
    } 
} 

Ich denke jedoch, dass statischen const mit Speicher im kompilierten Code für INVALID_RESP verbrauchen würde. Die Anweisung würde auch in Maschinencode übersetzt werden, der eine LOAD aus dem Speicher gefolgt von dem Vergleich ausführt, anstatt mit einem Wert zu vergleichen, der als Teil der Anweisung bereitgestellt wird. Ist das richtig? Wenn ja, dann wäre diese Lösung in Bezug auf Geschwindigkeit und Speicher nicht optimal, oder?

ich zur Zeit den Code ändern #defines zu verwenden

void checkInvalidResponse (uint8_t response) 
{ 
    #define INVALID_RESP 0xFF 

    if (response == INVALID_RESP) 
    { 
     /* Code for invalid response */ 
    } 
} 

Da jedoch #define keinen Spielraum hat, würde das Verhalten des Cut-and-Paste Aspekts #define über mehr konsistent sein Compiler? Zum Beispiel, wenn INVALID_RESP später neu definiert wird, würde irgendein Code in Zeilen nach der Neudefinition den neuen Wert verwenden?

Ein weiterer Ansatz, den ich untersucht habe, ist die Verwendung von Aufzählungen.

void checkInvalidResponse (uint8_t response) 
{ 
    typedef enum 
    { 
     INVALID_RESP = 0xFF 
    } resp_t; 

    if ((resp_t)response == INVALID_RESP) 
    { 
     /* Code for invalid response */ 
    } 
} 

jedoch die Typumwandlung zu einem ENUM würde mehr Speicher als notwendig (der Prozessor einen 32-Bit (?) Vergleichen, statt eines 8-Bit-Vergleichen tun würde) zuzuteilen.

Was ist die beste Methode, anstatt magische Zahlen im Code zu verwenden?

+1

Sind Sie wirklich besorgt, wenn der Enum-Basistyp länger als 1 Byte ist? –

+1

Kluge Leute schlagen vor, dass es über '' define's überall möglich ist. –

+0

Sie können '' define' 'undefinieren', wo Sie entscheiden, dass Sie mit diesem Wert fertig sind ... – sps

Antwort

3

Ich denke in allen Fällen wird der Compiler, zumindest mit -O2 eingeschaltet, den gleichen Code generieren. Es ist ziemlich schwer geworden, Compiler zu dummen Sachen zu machen.

In der Regel werden magische Zahlen in einem gemeinsamen Header definiert und nach Bedarf im gesamten Code verwendet.

Die größere Frage für Sie ist, spielt es eine Rolle? Ist dies etwas, das sich auf dem kritischen Pfad Ihres Codes befindet, und etwas, das Sie zu einem sehr hohen Prozentsatz der Zeit tun werden? Angesichts des Namens würde ich nicht raten.

Wenn Sie die Definition in eine Headerdatei verschieben, wird Ihr Code weniger störend. In checkInvalidResponse, der Leser könnte nicht weniger genau, was durch INVALID_RESPONSE dargestellt wird, nur, dass der Test besteht oder nicht.

0

enum wird vom Standard garantiert, um unsigned int Breite zu unterstützen.

Wenn Sie #define verwenden gibt es keine implizite Spezifikation der Breite, da der Pre-Compiler nur das Symbol durch die Zahl (oder was auch immer definiert wurde) ersetzt, so dass Sie L an das Ende Ihrer Nummer und Garantie anhängen können long Werte.

Ehrlich gesagt, ich hatte nie Gebrauch für Aufzählungen größer als ganze Zahlen mich ...

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.7.2.2 Enumeration Bezeich
[...]
Constraints
der Ausdruck, Definiert den Wert einer Enumerationskonstante, die ein ganzzahliger konstanter Ausdruck ist, der einen Wert hat, der als int dargestellt werden kann.
[...]
Jeder Aufzählungstyp muss mit char, einem vorzeichenbehafteten Integer-Typ oder einem vorzeichenlosen Integer-Typ kompatibel sein. Die Wahl des Typs ist implementationsdefiniert, soll jedoch die Werte aller Mitglieder der Enumeration darstellen können.

1

In der Sprache C const Einheiten sind keine Konstanten auf der Sprachstufe, die deutlich die Brauchbarkeit von const zur Definition manifest Konstanten begrenzt. Beachten Sie, dass es hier nicht um die Effizienz des generierten Codes geht, sondern um die grundsätzliche Gültigkeit ("Kompilierbarkeit") des Codes: In C-Sprache const sind Entitäten in Kontexten, die Konstanten benötigen, einfach nicht erlaubt.

Aus diesem Grunde in der C-Sprache ist die einzigen wirklich universell und vielseitig Ansatz manifeste Konstanten zu definieren, C-Präprozessor (dh #define), mit enum anderen vialble Alternative zu sein, aber nur dort, wo es anwendbar ist (ein wesentlicher Nachteil von enum Konstanten in C ist die Tatsache, dass sie unbedingt unterzeichnet haben int Typ).

Verwenden Sie einfach #define und versuchen Sie nicht, die Konstanten "im Geltungsbereich". Es gibt keinen Grund, dies zu tun. Wenn Sie jedoch aus irgendeinem Grund den Gültigkeitsbereich #define 'd konstant halten müssen, können Sie immer #undef für diesen Zweck verwenden.

+0

Können Sie dies bestätigen. Soweit ich mich erinnere, setzt gcc konstant im .text-Bereich – doron

+1

@doron: Es geht nicht darum, wo der Compiler sie platziert. Es geht darum, dass in der C-Sprache "const" -Entitäten nicht als "Konstanten" der Sprache gelten. Es ist nicht erlaubt, "const" -Entitäten in "case" -Etiketten, Bitfeldbreiten, Nicht-VLA-Array-Größen usw. zu verwenden. Die Sprache verbietet dies und der Code wird einfach nicht kompiliert. Das Thema ist bereits gut durch Antworten in den Kommentaren abgedeckt. Das OP verwendete ein nicht repräsentatives Beispiel mit einem "if", das keine Konstante erfordert.Aber wenn sie stattdessen eine 'switch/case'-Anweisung verwenden, würde das Problem mit 'const' sofort offensichtlich werden. – AnT

+0

Danke dafür. Das ist ein unerwarteter Unterschied in C und C++ für mich. – doron

0

Dies wird alles Compiler-und Plattform-spezifisch sein. Und es sei denn, Sie müssen wirklich ein paar Bytes ausgleichen, um in ein ROM zu passen. Die Verwendung des Compilers ist fast immer weniger fehleranfällig als der Präprozessor, also bleib bei den Constants.

Bedenken Sie auch, dass der Compiler immer inline erlaubt ist, wenn es sinnvoller ist.

Verwandte Themen