Forum: Mikrocontroller und Digitale Elektronik Arduino const struct


von Bomwollen (Gast)


Lesenswert?

Guten Morgen zusammen!

ich möchte gerne etwas Ordnung in meine Konstanten bringen.
Wenn ich z.B. so was anstatt ungeordneter const-Werte oder #defines 
mache:
1
const struct game
2
{
3
  const uint8_t v_max;
4
  const uint8_t a_max;
5
  const uint8_t size_x;
6
  const uint8_t size_y;
7
  //...
8
};

Ist es so, dass game.size_x als Wert zum compilieren genommen wird und 
keine Laufzeit kostet?


danke Euch!

von Patrick C. (pcrom)


Lesenswert?

Was ist das nachteil von
#define GAME_V_MAX 23
#define GAME_A_MAX 5
(etc)

von Bomwollen (Gast)


Lesenswert?

Ich finde es übersichtlicher so. Das kann ich für mich wesentlich besser 
strukturieren und lesen.

Aber weißt du auch was zu meiner Frage zu sagen? Ist es auch wirklich 
vom Ergebnis äquivalent?

von Vincent H. (vinci)


Lesenswert?

Ich glaub was du eigentlich fragen willst ist:
"Ist es so, dass game.size_x als Wert im Flash landet und nicht im RAM?"

Und die Antwort ist ja. Ich glaub du solltest aber generell ein wenig 
über den const-qualifier lesen.
1
struct Game
2
{
3
  uint8_t v_max;
4
  uint8_t a_max;
5
  uint8_t size_x;
6
  uint8_t size_y;
7
};
8
9
// C++-style (="Arduino") seit zumindest C++11
10
constexpr Game game{1, 2, 3, 4};
11
12
// C-style
13
const Game game2{1, 2, 3, 4};


Und bitte verwend keine #defines...

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Bomwollen schrieb:
> Aber weißt du auch was zu meiner Frage zu sagen? Ist es auch wirklich
> vom Ergebnis äquivalent?

Das hängt vom Compiler ab. Wenn er will, kann er dein struct-Konstrukt 
so weit optimieren, dass derselbe Code rauskommt. Muss er aber nicht.

gcc macht's so. Allerdings nur, wenn erstens die Optimierung auf 
mindestens -O1 eingestellt ist und 2. er bei jeder Verwendung die 
gesamte struct inclusive ihrer Initialisierung zu sehen bekommt.

Ich halte die Vorgehensweise für keine gute Idee.

von Bomwollen (Gast)


Lesenswert?

Ich möchte eigentlich nicht nur wissen, ob das im Flash landet, sondern 
ob der compiler den constanten Wert auch benutzt.
Wenn das nur im Flash landet und dann bei Benutzung der Wert aus dem 
Flash geholt würde, dann dauert das ja.

von Bomwollen (Gast)


Lesenswert?

"Ich halte die Vorgehensweise für keine gute Idee."

Also du würdest eher #defines benutzen und versuchen die so gut es geht 
zu sortieren?

von Oliver S. (oliverso)


Lesenswert?

Markus F. schrieb:
> Das hängt vom Compiler ab.

Da der Compiler aber bekannt ist, (avr-gcc), wird er das wie gewünscht 
optimieren (wenn der Code soweit ergänzt wird, daß er kompilierbar 
wird).

Ich würde dafür allerdings einen namespace verwenden.
1
namespace game
2
{
3
    const int v_max {42};
4
}

Oliver

von Markus F. (mfro)


Lesenswert?

Bomwollen schrieb:
> "Ich halte die Vorgehensweise für keine gute Idee."
>
> Also du würdest eher #defines benutzen und versuchen die so gut es geht
> zu sortieren?

Wenn dein Arduino-Universum constexpr beherrscht (und Du auch), ist das 
- wie oben erwähnt - wahrscheinlich die beste Idee.

von Markus F. (mfro)


Lesenswert?

Oliver S. schrieb:
> Da der Compiler aber bekannt ist, (avr-gcc), wird er das wie gewünscht

ist er das? Wenn ich mich recht erinnere, gibt's Arduino in allen 
möglichen Geschmacksrichtungen und längst nicht mehr nur für AVR.

von Vincent H. (vinci)


Lesenswert?

Bomwollen schrieb:
> Ich möchte eigentlich nicht nur wissen, ob das im Flash landet, sondern
> ob der compiler den constanten Wert auch benutzt.
> Wenn das nur im Flash landet und dann bei Benutzung der Wert aus dem
> Flash geholt würde, dann dauert das ja.

Das hängt sehr stark von der von dir verwendeten Architektur ab, die 
unter "Arduino" ja mittlerweile sehr bunt ist. Alle mir gängigen 
modernen Compiler erzeugen für Literals optimalen Code.

Kann die Konstante in einen Maschinenbefehl codiert werden, dann wird 
dies auch geschehn (inkl. teils recht lustiger Tricks wie negieren 
usw.). Kann sie das nicht, dann bleibt dem Compiler nichts anderes übrig 
als sie im Flash abzulegen.

Ob du nun
1
int a += 42;

oder
1
constexpr int b = 42;
2
int a += b;

is dabei vollkommen egal.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bomwollen schrieb:
> Ist es so, dass game.size_x als Wert zum compilieren genommen wird und
> keine Laufzeit kostet?

In C wird const in Static Storage spätestens zur Load-Time bestimmt.

In C++ kann Static Storage const auch zur Laufzeit geändert werden, zum 
Beispiel kann der Compiler Startup-Code erzeugen, der einen const erst 
zur Laufzeit initialisiert, etwa in einem statischen Constructor wie in
1
extern int volatile v;
2
const int i = v; // Initialisierung zur Laufzeit
Wie es in deinem Falle liegt hängt ab vom Code und Optimierungen des 
Compilers.  Selbst wenn eine Initialisierung zur Load-Time möglich ist, 
ist ein C++ Compile m.W. nicht dazu verpflichtet, dies auch wirklich zur 
Load-Time auszuführen.

von Bomwollen (Gast)


Lesenswert?

Erst mal danke für den Thread. Der hat mir sehr geholfen und kam ohne 
traditionelles remgebolze aus! Obwohl ich noch Defizite habe. Zuletzt 
konnte ich den Unterschied zwischen const und constexpr lernen. Danke!

Den Weg mit einem Namespace mag ich derzeit am liebsten.

von Einer K. (Gast)


Lesenswert?

Ein Ziel bei der C++ Entwicklung war, die überflüssigen #define 
auszurotten.

Und darum geht es ean der stelle auch ohne.

Bomwollen schrieb:
> const struct game
> {
>   const uint8_t v_max;
>   const uint8_t a_max;
>   const uint8_t size_x;
>   const uint8_t size_y;
>   //...
> };

Das ist auch eine schlechte Idee...
Wg. zusätzlicher Dereferenzierung


Mein Vorschlag:
Stropfe sie in einen anonymen Namespace.
So sind sie gruppiert und dennoch, ohne Klimmzüge oder zusätzliche 
Dereferenzierung, erreichbar.

Patrick C. schrieb:
> Was ist das nachteil von
> #define GAME_V_MAX 23
> #define GAME_A_MAX 5
> (etc)

Fehlende Typeprüfung.
Kryptische Fehlermeldungen.

#define ist eine alte C Krankheit, welche nach C++ mit rüber geschleppt 
wurde.
mittlerweile gibts schon recht gute Gegenmittel.
So muss heutzutagen nicht mehr jedes Programm unter der #Defineritis 
leiden.

Wer ohne Not #define verwendet stellst sich selber ein Bein damit.
Und das wollen wir doch nicht!

von Markus F. (mfro)


Lesenswert?

Das ist hier gar nicht gefragt. Der Fragesteller will - wenn ich das 
richtig verstehe - nur wissen, ob der Compiler seine Konstanten als 
Literale verwendet (also insbesondere, ob Berechnungen mit den 
Konstanten - wo möglich - bereits zur Compile-Zeit ausgeführt werden).

Meiner bescheidenen Meinung nach ist das nur mit constexpr einigermassen 
gesichert.

von Oliver S. (oliverso)


Lesenswert?

Markus F. schrieb:
> Meiner bescheidenen Meinung nach ist das nur mit constexpr einigermassen
> gesichert.

Meiner bescheidenen Erfahrung nach macht der gcc das mit const sehr 
zuverlässig.

Oliver

von Einer K. (Gast)


Lesenswert?

Markus F. schrieb:
> Wenn dein Arduino-Universum constexpr beherrscht

Tut es, in den den neueren Versionen.
Aktuell ist wohl c++11 für den AVR Core

Und in der Hardware Definition, kann man das auch noch hochsetzen.
-std=gnu++14
Dann gehen auch Schleifen in constexpr usw.

Oliver S. schrieb:
> Meiner bescheidenen Erfahrung nach macht der gcc das mit const sehr
> zuverlässig.
Ja!
Für einfache Berechnungen ausreichend.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.