C Größe eines enum beeinflussen?

  • Das Forum bekommt am Sonntag 17.11.2019 um 9:00 Uhr ein Update!
    In der Zeit wird das Forum leider nicht erreichbar sein!

    Das Update wird voraussichtlich 2 bis 3 Stunden dauern.

Janiiix3

Aktives Mitglied
28 Sep 2013
1.321
10
38
Hannover
Sprachen
C, C#
Nabend,

wenn ich das richtig verstanden habe bestehen die einzelnen Member eines enums (AVR GCC) aus einem signed int?
Kann ich mit dem Attribut "_attribut(packend)" auf die tatsächliche Größe die benötigt wird (uint8) komprimieren?
 

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
Ist ja schön, daß Du Dir Gedanken machst, wie man Platz sparen könnte.

Was schätzt Du denn, wieviele Bytes Du einsparen würdest?

Der GCC optimiert recht gut und wenn ich davon ausgehe, daß Deine enum-Aufzählung kleiner als 256 ist, dann würde ich mal annehmen, daß der Compiler Vergleiche mit oder Zuweisungen zu uint8_t-Variablen von sich aus so optimiert, daß Du mit Deinem Vorhaben keine weitere Einsparung erreichen wirst.
 

Janiiix3

Aktives Mitglied
28 Sep 2013
1.321
10
38
Hannover
Sprachen
C, C#
Es geht mir in erster Linie darum was zu lernenden.
So wie ich das gelesen habe sind die Werte von einem enum default vom Typ signed int..
Wenn man das nicht konkret in irgendwelchen Compiler Optionen einbettet oder eben diese attribut nutzt wird halt eine signed int Konstante genutzt, egal ob der Wert auch in eine 1 Byte Variable passen würde.

Kann ich denn im Endeffekt in irgendeiner Output Datei sehen was jetzt genau welchen und wie viel Speicher in Anspruch genommen hat?
 

LotadaC

Sehr aktives Mitglied
22 Jan 2009
3.340
61
48
Marwitz
Sprachen
BascomAVR, Assembler
Kann ich denn im Endeffekt in irgendeiner Output Datei sehen was jetzt genau welchen und wie viel Speicher in Anspruch genommen hat?
Ob das irgendwo Hochsprachenprogrammierer-freundlich geloggt wird weiß ich nicht, aber grundsätzlich solltest Du es (A) im Simulator verfolgen können oder (B) im (ggf reassemblierten) HEX-File erkennen.

Warum soll überhaupt für eine Aufzählung ein Vorzeichen verwendet werden? Das Vorzeichen kommt doch nur bei Rechenoperationen zum tragen. Hast Du n diskrete … äh Dinger, Zustände oder wie auch immer Du die nennen willst zu unterscheiden/abzuspeichern, benötigst Du lg(n) Bits.

Der GCC optimiert recht gut und wenn ich davon ausgehe, daß Deine enum-Aufzählung kleiner als 256 ist, dann würde ich mal annehmen, daß der Compiler Vergleiche mit oder Zuweisungen zu uint8_t-Variablen von sich aus so optimiert,
 

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
wird halt eine signed int Konstante genutzt
Hast Du das ausprobiert? Wenn nicht, schreib ein Programm, starte den Debugger oder
und schau Dir das Disassembler-Listing an. Probiere alle Optimierungen von -O0 bis -O3 und -Os durch, dann hast Du was gelernt. Und kannst uns hier berichten, was Du rausgefunden hast. ;)
(Im Simulator/Debugger ist der C-Quellcode zu sehen, im disassemblierten HEX-File nicht, ist im Letzteren also wesentlich schwieriger eine bestimmte Stelle zu finden, ohne das ganze Programm zu analysieren.)
Warum soll überhaupt für eine Aufzählung ein Vorzeichen verwendet werden?
Das haben Kernighan & Ritchie in einer der ersten C-Definitionen Anfang der 70er so festgelegt und da bisher vermutlich niemand eine Aufzählung mit mehr als 32767 Elementen benutzt hat, ist es wohl noch nie jemandem aufgefallen… ;)
 

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Ist ja schön, daß Du Dir Gedanken machst, wie man Platz sparen könnte.
...
Der GCC optimiert recht gut und wenn ich davon ausgehe, daß Deine enum-Aufzählung kleiner als 256 ist, dann würde ich mal annehmen, daß der Compiler Vergleiche mit oder Zuweisungen zu uint8_t-Variablen von sich aus so optimiert, daß Du mit Deinem Vorhaben keine weitere Einsparung erreichen wirst.
Bei C kenne ich mich nicht aus, aber bei C# und VB.Net liegst du hier falsch. Die sind immer Int32. Daher ist die Frage gar nicht so dumm, vor allem wenn meinen Enum Wert unbekannter Breite in einer Struktur hat. Will man diese jetzt aus einem Datenstrom auslesen, dann wird es lustig...

Ich spreche hier aus Erfahrung, weil alte VB Versionen (ohne .Net) Integer (und somit Enums) noch 16 oder 32 Bit breit waren (je nach Version), die neuen VB.Net Versionen 32 Bit. Gibt die lustigsten Fehler.Vieles an Quelltext ist noch für VB6, Integer = 32 Bit. So oft wird ein Pointer (32 Bit auf 32 Bit Systemen, 64 auf 64) unbemerkt in einen Integer geprügelt. Klappt natürlich nur auf 32 Bit OS.
Ne, lieber fix angeben und nichts optimieren lassen wo man dann nicht weiß was raus kommt.
In VB.Net / C# geht das.
Public Enum MyEnum As UInt32

EDIT: Hatte aus Versehen Struct statt Enum geschrieben.
 
Zuletzt bearbeitet:

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
Public Structure MyStruct As UInt32
Eine struct- ist kein enum-Anweisung. Vielleicht gibt‘s die ja bei VB.Net / C# nicht (ich kenne weder das Eine noch das Andere).
Was Compiler für PCs betrifft, hast Du sicher recht, bei 4, 8 oder mehr GB RAM bei 64 Bit Breite, lohnt es sich nicht zu sparen, aber
Die AVRs haben 8 Bit und 0 bis (meistens nicht mehr als) 8 Kilobytes RAM.
Und der AVRGCC optimiert recht gut, wie gesagt.
Das erinnert so an Äpfel und Birnen…
Aber da hilft wohl nur ausprobieren, wenn man es wirklich wissen will.
 

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Ja, nein, ich meine es anders.
Wenn du in einer Struktur eine Enum mit einer (für dich) variablen Breite hast. Jetzt empfängst du die erwarteten x Bytes, liest die als Struktur aus, wie du denkst dass sie umgesetzt wurde. Wurde sie aber nicht. Dann ist dein kompletter Datenstrom durcheinander.
Bei AVR gehe ich auch von 8 Bit Breite aus, aber wer weiß das schon.

Und klar gibt es Enums. meinte ich auch. Kommt davon wenn man abgelenkt wird. Korrigiert.
 

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
wer weiß das schon
Steht im Eröffnungsbeitrag.
Soweit ich weiß, kennt der AVRGCC für enums nur int (16 Bit).
Mag sein, daß man das irgendwo ändern kann, aber soweit bin ich noch nicht in die Abgründe des Compilers hinabgestiegen.
Ohne Optimierung wird der AVRGCC auch mit 16 Bit vergleichen oder zuweisen, wahrscheinlich sogar eine Warnung ausgeben, wenn man 8 und 16 Bit vermischt (zumindest bei -pedantic), aber die Optimierung ist bei AtmelStudio standardmäßig eingeschaltet und wenn es keine Warnung oder Fehler gibt, vermute ich, daß er das wegoptimiert.
 

Dirk

Administrator
Teammitglied
28 Jan 2007
4.281
141
63
Mittelhessen, Giessen
Sprachen
C, C++, C#, Pascal, Assembler, PHP, Java
Das mit enum in einer Struktur und die Struktur dann in einem Datenstrom übertragen, hatte ich auch schon mal. Da ich sowieso zwischen zwei unterschiedlichen Systemen Daten ausgetauscht hatte (Windows/Delphi und AVR/GCC) und ich mir auch nicht hundertprozentig sicher war ob die Strukturelemente die selbe Annordnung/Reihenfolge haben, hatte ich dann alle Elemente einzeln betrachtet und übertragen, nicht die Struktur in einem Memorystream.

Wichtig ist die Größe des enum eventuell auch, wenn man sowas im NVM (Flash, Eeprom) ablegt.

Um die Datengröße der Enums zu minimieren, kann man die Lösung mit attribute packed verwenden. Es gibt auch einen Compiler Switch:
Compiler Option
-fshort-enums

Allocate to an enum type only as many bytes as it needs for the declared range of possible values. Specifically, the enum type will be equivalent to the smallest integer type which has enough room.
Wenn man enums mit größer als 2 Byte haben möchte, kann man glaube auch ein einzelnes Element mit zB einer 32Bit Zahl definieren, dann wären alle Elemente 32Bit also 4Byte.

Die Größe läßt sich prüfen mit sizeof().
 
  • Like
Wertungen: Mikro23 und TommyB

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Du empfängst (Seriell, Netzwerk, I2C, whatever) 0x1234567890ABCDEF und wandelt es direkt in eine Struktur um.
Struct MyStruct
Var1 As Int32
Var2 As MyEnum (=Byte)
Var3 As UInt16
Var4 As Byte
End Struct

Was passiert jetzt wenn die Enum kein Byte ist sondern 2 oder 4? ;)
 
  • Like
Wertungen: Dirk

Janiiix3

Aktives Mitglied
28 Sep 2013
1.321
10
38
Hannover
Sprachen
C, C#
Du empfängst (Seriell, Netzwerk, I2C, whatever) 0x1234567890ABCDEF und wandelt es direkt in eine Struktur um.
Struct MyStruct
Var1 As Int32
Var2 As MyEnum (=Byte)
Var3 As UInt16
Var4 As Byte
End Struct

Was passiert jetzt wenn die Enum kein Byte ist sondern 2 oder 4? ;)
So wandelt man es doch never in eine Struktur um?

Jetzt habe ich das mit den Farben auch verstanden..
Spielt die Größe da eigentlich keine Rolle? Du empfängst ein Byte und speicherst es evtl. In ein 2 Byte großes enum ab.. Sollte keine Rolle spielen oder?
 
Zuletzt bearbeitet:

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Was meinste was dein Kompiler macht? Der speichert die Metadaten (also die Struktur der Struktur), aber die Daten selbst werden hintereinander abgelegt. Ist in C, C++, C# und VB.Net so und garantiert überall anders auch. Serialisiert man das jetzt (bei C reicht glaube ich ein Casting, in .Net wäre es Marshal) kommst du an eben genau diese Daten.
 

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
Var2 As MyEnum (=Byte)
Var2 ist eine Variable. MyEnum ist ein Datentyp.
Du empfängst ein Byte und speicherst es evtl. In ein 2 Byte großes enum ab
enum ist eine Aufzählung, ein Datentyp, keine Variable!
enum ist eine Liste von Namen, die stellvertretend für Zahlen stehen, die der Compiler intern verwendet.
Du brauchst Dir nur die Namen zu merken, der Compiler kümmert sich darum, die passenden Zahlen einzusetzen. In dieser Liste von Namen kann nichts gespeichert werden.
 

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Du brauchst Dir nur die Namen zu merken, der Compiler kümmert sich darum, die passenden Zahlen einzusetzen. In dieser Liste von Namen kann nichts gespeichert werden.
Falsch. Es ist eine (Quelltext-) Variable, nur mit benutzerdefiniertem Typ. Du kannst Enums zumindest in .Net auch auf verschiedenen Wegen beeinflussen.


CodeBox VisualBasic
Dim Var1 As MyEnum = MyEnum.Value1
Dim Var2 As MyEnum = MyEnum.Value2
Enum MyEnum As Byte
Value1 ' Kein Wert vorgegeben, es geht von 0 ++
Value2 = 123 ' außer hier, da angegeben
...
End Enum

Var1 wäre effektiv 0. Unnötig zu sagen was Var2 ist. Also aus digitaler Sicht.

Oder:


CodeBox VisualBasic
<Flags()> Enum MyEnum As Byte
Value1
Value2
Value3
Value4
End Enum

Hier wäre Value1 = 0, Value2 = 1, Value3 = 2, Value4 = 4, ... weil bitweise gezählt wird (außer explizit angegeben)

Wer kein VB.Net mag, sondern lieber C: https://www.pinvoke.net/default.aspx/Enums.WindowsMessages
Oder lokal: winuser.h
 
Zuletzt bearbeitet:

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
Falsch. Es ist eine (Quelltext-) Variable
In C ist enum ein Datentyp, keine Variable.
Du kannst Variablen mit dem als enum definierten Datentyp definieren, aber in dem Datentyp selbst nichts speichern.

CodeBox C
enum week { Mon=1, Tue, Wed, Thu, Fri Sat, Sun} days;
week ist hier der Datentyp, days eine Variable. Du kannst jetzt mit

CodeBox C
enum week tage;
die Variable tage vom Typ enum week definieren.
 

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Ist in VB.Net nix anders, trotzdem werden den Namen Werte zugewiesen mit denen weiter gearbeitet wird. Die Frage ist nur welchen Datentyp der automatisch generierte Wert hat. Wie ais deinem Link:
Wenn eine Variable mit enum definiert wird, behandelt sie der Compiler als Integerzahl.
Aber wie breit ist ein Integer? Das variiert leider. Daher wäre eine strikte Angabe sinnvoll.
 

Mikro23

Aktives Mitglied
2 Jan 2017
362
33
28
Großraum Hannover
Sprachen
C, Assembler
Aber wie breit ist ein Integer? Das variiert leider. Daher wäre eine strikte Angabe sinnvoll.
Ja, das variiert aber nicht bei ein und demselben Compiler, in diesem Fall AVRGCC und da hat ein integer (bzw. enum) immer 16 Bit, wenn man es nicht, wie Dirk oben schrieb, in den Compileroptionen ändert.
trotzdem werden den Namen Werte zugewiesen
Nochmal. Den Namen Mon, Tue, Wed... oder week können keine Werte zugewiesen werden, erstere sind Stellvertreter für Zahlen, die den mit dem entsprechenden Typ definierten Variablen zugewiesen werden können , das Letztere einem Datentyp.
Außerdem gibt es auch noch Variablennamen, das ist wieder was ganz anderes.
Wahrscheinlich meinst Du mit Namen was anderes als ich. ;)
 

TommyB

Team Bitschubse
Premium Benutzer
17 Mai 2010
2.151
80
48
36
127.0.0.1 ;)
Sprachen
C#, VB.Net, LunaAVR, Assembler, Python
Ja, das variiert aber nicht bei ein und demselben Compiler, in diesem Fall AVRGCC und da hat ein integer (bzw. enum) immer 16 Bit, wenn man es nicht, wie Dirk oben schrieb, in den Compileroptionen ändert.
Das kann sein. Verlassen würde ich mich nicht drauf. Ich deklariere immer explizit.
Und das ist auch notwendig wenn man zwischen verschiedenen Plattformen (AVR/PC) arbeitet, GCC hin oder her. Wenn eine Kommunikation besteht muss man wissen wie breit ein Integer oder eine Enum ist (PC=32Bit). Knack, Protokoll hinüber. Da werden die Datenpakete denn mal eben größer/kleiner als erwartet.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)