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
enumReqCodes{REQUEST=1,REPEAT=8,RESET=127};// Commandos fuer das Request Telegramm zur Sonde
2
3
unionTxArrayWortConverter
4
{int16_tWortArray[TelLen];// Arrayzugriff ueber Index mit DatTxBuf.WortArray[Index]
5
structReqTel// Struktur Typ Name fuer Request Telegramm
6
{uint16_tCommand;// Einzelwort Zugriffe mit DatTxBuf.Einzelwert.Command
7
uint16_tnc1;
8
uint16_tnc2;
9
uint16_tnc3;
10
uint16_tnc4;
11
uint16_tnc5;
12
uint16_tnc6;
13
uint16_tChkSum;
14
}Einzelwert;
15
}DatTxBuf;// sofortige Reservierung von 32 Bytes unter dem Variablennamen TxDatBuf, Union Typname deshalb hier belanglos
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
enumReqCodes{REQUEST=1,REPEAT=8,RESET=127};
2
3
unionTxArrayWortConverter{
4
int16_tWortArray[TelLen];
5
structReqTel{
6
uint16_tCommand;// <====
7
...
8
}Einzelwert;
9
}DatTxBuf;
beissen sich. Z.B. eine Abfrage wäre ein Cast Gewurschtel
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
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.
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).
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.
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
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.