Forum: Compiler & IDEs Anfängerfrage zu Enum Datentyp


von Janvi (Gast)


Lesenswert?

ich habe ein Telegramm zu einem Fremdrechner welches in einem struct 
(ReqTel) im DatTxBuf liegt. Das erste Wort ist nun ein Kommando, welches 
ich per enum belegen möchte. Wie kann ich jetzt sicherstellen, daß der 
enunm auch eine Größe von int16_t einhält? Wenn der Compiler jetzt 
uint8_t als Code generieren würde, hätte der Rechner auf der 
Empfangseite wegen einem zu kurzen Telegramm bzw. wegen verschobenen 
Folgedaten und Prüfsumme ein Problem. Besser ohne enum mit einem define 
?
1
enum ReqCodes {REQUEST=1, REPEAT=8, RESET=127};   // Commandos fuer das Request Telegramm zur Sonde
2
3
union  TxArrayWortConverter          
4
    {int16_t WortArray[TelLen];    // Arrayzugriff ueber Index mit DatTxBuf.WortArray[Index]
5
     struct ReqTel              // Struktur Typ Name fuer Request Telegramm
6
      {uint16_t  Command;    //  Einzelwort Zugriffe mit DatTxBuf.Einzelwert.Command
7
       uint16_t  nc1;      
8
       uint16_t  nc2;      
9
       uint16_t  nc3;      
10
       uint16_t  nc4;     
11
       uint16_t  nc5;      
12
       uint16_t  nc6;     
13
       uint16_t  ChkSum;      
14
      }Einzelwert;
15
    } DatTxBuf;                // sofortige Reservierung von 32 Bytes unter dem Variablennamen TxDatBuf, Union Typname deshalb hier belanglos

von Helfer (Gast)


Lesenswert?

http://www.nongnu.org/avr-libc/user-manual/FAQ.html
What registers are used by the C compiler?

    * Data types:
      char is 8 bits, int is 16 bits, long is 32 bits, long long is 64 
bits, float and double are 32 bits (this is the only supported floating 
point format), pointers are 16 bits (function pointers are word 
addresses, to allow addressing up to 128K program memory space). There 
is a -mint8 option (see Options for the C compiler avr-gcc) to make int 
8 bits, but that is not supported by avr-libc and violates C standards 
(int must be at least 16 bits). It may be removed in a future release.

http://msdn.microsoft.com/en-us/library/whbyts4t(v=vs.80).aspx
"In ANSI C, the expressions that define the value of an enumerator 
constant always have int type; thus, the storage associated with an 
enumeration variable is the storage required for a single int value. An 
enumeration constant or a value of enumerated type can be used anywhere 
the C language permits an integer expression."

=>
1
enum ReqCodes {REQUEST=1, REPEAT=8, RESET=127}; 
2
3
union TxArrayWortConverter {
4
  int16_t WortArray[TelLen];
5
  struct ReqTel {
6
    uint16_t  Command;   // <====
7
    ...
8
  } Einzelwert;
9
} DatTxBuf;

beissen sich. Z.B. eine Abfrage wäre ein Cast Gewurschtel
1
if( (( enum ReqCodes ) DatTxBuf.Einzelwert.Command) == RESET ) {

Alternative:
1
union TxArrayWortConverter {
2
  int16_t WortArray[TelLen];
3
  struct ReqTel {
4
    enum ReqCodes Command;   // <====
5
    ...
6
  } Einzelwert;
7
} DatTxBuf;   
8
9
// =>
10
11
if( DatTxBuf.Einzelwert.Command == RESET ) {

> Besser ohne enum mit einem define?
Googel mal nach "difference enum define macro", Vor- und Nachteile 
werden da genannt.

von Janvi (Gast)


Lesenswert?

ok, also wenn ich etwas Glück habe ist der Integer von enum 16 bit wie 
ich es brauche. Ansonsten hätte ich eben Pech. Der Compiler ist übrigens 
GCC mit Zielsystem Cortex M3, also ein 32 bit Code. Aber ich probier 
einfach mal und nehm im Zweifelsfall dann doch define

von J. V. (janvi)


Lesenswert?

Bei struct ReqTel {enum ReqCodes Command;...  ergibt 
sizeof(DatTxBuf.Einzelwert.Command) leider eine 4. Kann man das bei der 
Definition irgendwie auf uint16_t casten ? Der Debugger zeigt die enum 
Einträge nämlich gut als Klartext an, was eine ziemlich geile Optik 
macht.

von Stefan E. (sternst)


Lesenswert?

Irgendwie kann ich das Problem nicht nachvollziehen. Benutze in der 
struct doch ein uint16_t, wenn es denn genau 16 Bit sein müssen. Du 
kannst dem doch jederzeit ein enum zuweisen oder mit einem enum 
Vergleichen. Das verwenden der enum in der struct hat sowieso keine 
beschränkende Wirkung darauf, was man DatTxBuf.Einzelwert.Command 
zuweisen kann (sofern wir hier von C reden).

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Na, der Reiz der Verwendung des enums selbst liegt für "J.V." darin, daß 
der Debugger dann nicht numerische Werte, sondern die symbolischen Namen 
anzeigt.

von Klaus (Gast)


Lesenswert?

Janvi schrieb:
> ich habe ein Telegramm zu einem Fremdrechner welches in einem struct
> (ReqTel) im DatTxBuf liegt.

Das ist ein grundsätzliches Problem bei einer Datenkommunikation 
zwischen (verschiedenen) Rechner. Es trifft nicht nur enums, sondern 
auch alle anderen Datentypen größer als ein Byte, für die nur eine 
Mindestgröße vorgegeben ist. Und nicht nur die Größe sondern auch die 
endianess kann ein Problem sein. Stichwort ist da network byte order. 
Dieses Problem wird typischerweise dadurch gelöst, daß die Daten in 
ASCII übertragen werden. Bei den heutigen Datenraten kommt es nicht 
darauf an, ob ein integer als 4 Byte oder als 1 bis 11 ASCII Bytes 
übertragen werden. Die meisten Daten wie Texte oder Multimedia sind 
sowieso Byte-Streams.

Die richtige Lösung ist also eine Übertragung im Klartext, dann zeigt 
nicht nur der Debugger, sondern auch jeder Network Sniffer das richtige 
an. Und als Nebeneffekt hat auch der Entwickler, der in 5 oder 10 Jahren 
einen neuen Node mit einem 128 Bit Prozessor baut, kein Problem mit der 
enum Größe in einem Modul, für daß es kein Datenblatt mehr gibt.

MfG Klaus

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Helfer schrieb:
> "In ANSI C, the expressions that define the value of an enumerator
> constant always have int type; thus, the storage associated with an
> enumeration variable is the storage required for a single int value.

Die erste Aussage ist richtig, die Schlussfolgerung daraus ist falsch.
Auch wenn GCC im Regelfall hier genauso entscheidet wie Microsoft-C,
der ISO-Standard lässt es ausdrücklich dem Compiler offen, welche
genaue Größe er einer enum-Variablen zuweist, und IAR beispielsweise
weist nur die minimal notwendige Größe zu (GCC macht dies mit
-fshort-enums oder mit __attribute__((packed))).

Hier das entsprechende Zitat aus dem Standard:

“Each enumerated type shall be compatible with char, a signed integer
type, or an unsigned integer type. The choice of type is
implementation-defined,113) but shall be capable of representing the
values of all the members of the enumeration. [...]

113) An implementation may delay the choice of which integer type
     until all enumeration constants have been seen.”

Es gibt also keinen portablen Weg, da ein enum zu benutzen und
gleichzeitig eine bestimmte Größe zu erzwingen.

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.