static const vs. #define in c ++ - Unterschiede in der ausführbaren Dateigröße

9

Meine grundlegende Situation: Ich habe eine Include-Datei, die etwas wie #define foo (Flag1 | Flags2 | Flag3) hat, also ist es eine vordefinierte Kombination von Bit-Flags. Aus Gründen der Typ-Sicherheit wollte ich diese #defines durch statische Constants ersetzen, d. H.% Co_de% (oder ähnlich). Diese Include-Datei ist an Dutzenden von Stellen im Programm enthalten.

Wenn ich jetzt einen Release-Build mit allen relevanten Optimierungsoptionen (mit dem C ++ - Compiler von VS2010) mache, scheint das Ersetzen der #defines die ausführbare Datei um einige KiB zu erhöhen, abhängig davon, wie viele Konstanten ich ersetze.

Warum passiert das? Meiner Meinung nach sollen Integer-Konstanten in den ASM-Code, der wenn möglich erzeugt wird, "eingezeichnet" sein, und ich sehe nicht, wie die Verwendung von static const int foo = (Flag1 | Flag2 | Flag3) vs static const hier einen Unterschied machen würde. Natürlich ist die Variable nicht inline, wie die Demontage zeigt:

%Vor%

Die letzte Frage ist also: Wie kann ich #define vermeiden, aber immer noch darauf vertrauen, dass die Variable direkt in die generierte Assembly eingefügt wird?

    
j_schultz 02.08.2012, 14:17
quelle

5 Antworten

0

Wie in den Kommentaren zu sehen ist, ist der typsichere Operator | Das Überladen für meine Enums scheint VC ++ daran zu hindern, den ORed-Wert zu inlinern. Ich nehme an, ich werde weiterhin die #define Version verwenden, da ich die Größe der ausführbaren Datei nicht hebe, wenn es keine Vorteile gibt (nein, das ist keine vorzeitige Optimierung) - immerhin erhöht es nicht die Lesbarkeit und da die Kombination von Flags ist schon von meinem Flagset-Enum-Typ, ich verliere auch keine Art-Sicherheit, schätze ich.

    
j_schultz 03.08.2012, 12:20
quelle
3

Es gibt keinen Grund, warum der Compiler die statische const-Variable nicht eliminieren konnte. Wenn Sie mit optimierten Kompilierungen kompilieren, bin ich überrascht, dass VC ++ dies nicht tut.

Ich habe versucht, diesen Code mit gcc zu kompilieren.

%Vor%

Bei deaktivierten Optimierungen wurde der Wert in den Wert eingezeichnet, aber immer noch reservierter Speicherplatz für die Variable.

%Vor%

Bei O2 wurde der Wert eingezeichnet und der Speicherplatz wurde gelöscht.

%Vor%

Mein anderer Gedanke, dass falsche Compiler-Einstellungen oder VC ++ diese Optimierung nicht vornehmen, ist, dass die Flags-Variablen keine Kompilierzeit-Konstanten sind, was bedeuten würde, dass der Wert des Ausdrucks beim Programmstart berechnet werden muss , was Inlining verhindern würde.

    
Dirk Holsopple 02.08.2012 14:49
quelle
0
%Vor%

usw. ...

und dann haben Sie den Wert direkt in der Anweisung, und Sie werden auch Typ überprüfen :) und ohne Optimierungsparameter.

Meiner Meinung nach ist der static const int BLABLA=1; stuff nur dazu da, einigen Konstanten einen Namespace hinzuzufügen ... und mehr RAM und RAM Zugriff im Code zu verwenden, was wirklich sinnlos ist, wenn das Symbol für eine #define Konstante hat eindeutig sein, und wenn der Verweis auf einen Fehlercode im Speicher weniger konsistent ist (jeder Malware / Fehler kann diese Werte in RAM zur Laufzeit ändern) als der unmittelbare Wert dieses Fehlercodes direkt in der Anweisung.

Aber es geht mehr um moderne Programmpolitik ... einige werden behaupten, public static const int zu verwenden, und andere (wie ich und Microsoft) bevorzugen die einfachere Version #define .

    
user2618714 18.03.2014 13:18
quelle
-2

Sie können Ihr Problem lösen, indem Sie es aus einer anderen Perspektive betrachten: Sie können die Daten und die Funktionen, die es verwenden, genau zusammensetzen.

In einer OO-Sprache bedeutet dies, dass Ihre Konstante foo zu einem privaten statischen Attribut einer Klasse wird. Diese Klasse sollte als öffentliche Methoden alle Funktionen haben, die foo verwenden. Da es sich um ein statisches privates Attribut handelt, wird es in der CPP-Datei definiert, und im ausführbaren Footprint wird nur eine Instanz davon vorhanden sein.

Ich verstehe, dass dies eine große Änderung in Ihrem Code wäre, und nicht eine einfache Reaktivierung: sicherlich ist es nicht so einfach wie die Definition von foo von #define auf eine statische globale Konstante zu modifizieren. Aber Daten und Methoden, die sie nahe beieinander verwenden (d. H. In derselben Klasse), bringen Ihnen viele nicht-funktionale Vorteile.

    
Daniele Pallastrelli 02.08.2012 14:35
quelle
-2

Ich nehme an, dass Sie static const int foo = (Flag1 | Flag2 | Flag3) in einer Header-Datei haben. Dies bewirkt, dass eine Version der Konstante in jeder Objektdatei separat gespeichert wird. Die # define bettet das Literal ein, das alle durch Pooling kombiniert werden.

Versuchen Sie dies, in einer C ++ Datei haben Sie const int foo = (Flag1 | Flag2 | Flag3) , dann in der Kopfzeile extern const int foo .

Aktualisieren

Tut mir leid, wenn meine Antwort nicht Ihren Bedürfnissen entspricht. Ich habe die Frage der Dateigröße für statische const-Variablen angesprochen.

Ich denke, es ist alles was du willst. Sofern ein Codeabschnitt keine Leistungsprobleme verursacht, würde ich mich niemals über diese Art der Optimierung Gedanken machen. Für mich sind Sicherheit und Dateigröße Dinge, die ich über der CPU-Optimierung schätze. Darüber hinaus ermöglicht eine externe const eine bessere Analyse durch Coverage und Timing-Tools.

  

Vorzeitige Optimierung ist die Wurzel allen Übels (oder zumindest des größten Teils davon) beim Programmieren.

- Donald Knuth

    
Jeffery Thomas 02.08.2012 14:36
quelle

Tags und Links