Hi @ all
Ich verwende den ATMEGA 32 von Atmel. Dort möchte ich aus einem 16Bit
unsigned Integer zwei 8 Bit unsigned Char erzeugen. Jedoch weiß ich
nicht wie ich dies anstellen soll?
Das ganze soll in C programmiert werden. Kann mir vielleicht einer einen
Codeschnipsel erzeuegen?
unsigned int i;
unsigned char LowByte;
unsigned char HighByte;
....
Also wenn ich einer 8 Bit Variable einen 16Bit Wert zuweise, werden nur
die unteren 8Bit (Bit 0 bis 7) übernommen.
HighByte = i >> 8;
Schiebt dieser Befehl die Daten erst 8 stellen nach links und übernimmt
dann Bit 0 bis Bit 7?
Hallo ich weiss jetzt nicht gerade, ob das so funktioniert aber
irgendwie in diese Richtung gehts wohl:
1
unionmy_converter
2
{unsignedinti;
3
unsignedchara;
4
unsignedcharb;
5
}u;
6
7
u.i=irgendein_input;
8
u.a=erster_output;
9
u.b=zweiter_output;
Da ich gerade keine Möglichkeit habe, das jetzt zu prüfen, könnte
vielleicht irgendein "alter Hase" aus dem Forum sagen, ob das geht oder
wie man es besser macht?
Gruss und viel Erfolg
ME
Sorry, für meine falsche Antwort von gestern Abend.
Die ist etwas zu schnell gekommen. Wollte soeben eine Korrektur
nachliefern, aber da das bereits Jörg G. und Fabian Ostner getan
haben, erübrigt sich das.
Gruss
ME
> Oder mache es mit einer union.> das ist das einfachste!
Vom Verständnis her ist beides gleich einfach - finde ich jedenfalls.
Der Union-Ansatz hat eine gewisse "geniale Eleganz", das geb ich zu.
Nachteil ist aber, man muss sich um Byte-Order und Struct-Alignment
Gedanken machen und den Compiler überzeugen, es genau so zu machen wie
man möchte.
Und selbst dann ist fraglich, ob das Reinkopieren des 16-Bit-Datums in
die Union-Variable und das Wieder-Rauskopieren der einzelnen Bytes nicht
mehr Code erzeugt als ein bisschen Schieben und Maskieren.
tuppes wrote:
> Und selbst dann ist fraglich, ob das Reinkopieren des 16-Bit-Datums in> die Union-Variable und das Wieder-Rauskopieren der einzelnen Bytes nicht> mehr Code erzeugt als ein bisschen Schieben und Maskieren.
Das Rein/Rauskopieren könnte man mit geeigneter Casterei (die man in
einem Makro versteckt) umgehen. Die Idee ist, den Compiler dazu zu
zwingen, einen int als eine derartige Struktur aufzufassen und dann
entsprechend zuzugreifen.
Byte Order ist natürlich ein Problem, struct-Alignment sollte aber
keines sein. Von einem Array ist geregelt, wie es abgelegt werden muss.
1
typedefunionuint2uchar
2
{
3
unsignedintw;
4
unsignedcharb[2];
5
};
6
7
#define HI_BYTE(X) ( ((uint2uchar*)&(X)).b[1] )
8
#define LO_BYTE(X) ( ((uint2uchar*)&(X)).b[0] )
9
10
11
intmain()
12
{
13
inti=25;
14
15
writeByte(LO_BYTE(i));
16
writeByte(HI_BYTE(i));
17
}
Ob das allerdings weniger Code erzeugt, als die Schieberei? Von einem
ordentlichen Compiler erwarte (erhoffe) ich mir, das er hier die Absicht
erkennt und nicht lange rumschiebt, sondern gleich auf das richtige Byte
zugreift. Müsste man ausprobieren
kbuchegg schrieb:
> Von einem ordentlichen Compiler erwarte (erhoffe) ich mir, das er hier> die Absicht erkennt und nicht lange rumschiebt, sondern gleich auf das> richtige Byte zugreift. Müsste man ausprobieren
Ich hab jetzt mal mit AVR-GCC ausprobiert, ob der erkennt, dass er
nichts schieben muss:
Mein C-Sourcecode war:
Wie man sieht gibt es also keine überflüssigen Schiebeoperationen. Der
etwas lange Assemblercode kommt daher, dass ich mit der Option s=0
(keine Optimierung) kompiliert habe, da sonst der Compiler merkt, dass
meine Miniprogramm fast nichts tut und daher fast alles "wegoptimiert".
Gruss
ME
Johann wrote:
> unsigned int i;> unsigned char LowByte;> unsigned char HighByte;>> ....
jetzt auch noch mein Senf dazu :)
ich arbeite im Automotive Bereich, da sind Unions aus
Sicherheits-/Portierungsgründen weitestgehend verboten (MISRA Regeln).
Wir machen das einfach so:
1
LowByte=(unsignedchar)(i&0x00FF);/* Get LSB */
2
HighByte=(unsignedchar)((i&0xFF00)>>8);/* Get MSB */
Ich weiss, vieles von dem ist implizit, wie das Maskieren und das
Casten. Aber wie gesagt gehts hier um Portierung und Sicherheit.
Bevor gleich Stimmen laut werden, dass ein Integer nicht auf allen
Prozessoren 16 Bit hat: Das stimmt natürlich. Aber deshalb benutzen wir
auch nicht direkt "unsigned int" sondern u16 oder u32 z.B. und
"konfigurieren" so unsere Datentypen.
Gruss und gute nacht! :)
>> Könnte auch das gehen ?
Fast.
> unsigned char lowbyte = *( &VariableMit16Bit + 1) ;
Du musst hier zuerst die Adresse &VariableMit16Bit auf einen unsigned
char Pointer umcasten. Sonst greifen die Pointer-Arithmetik Regeln und
das + 1 erhöht dir die Adresse um 2
> Oder liegen LSB und MSB umgekehrt im RAM ?
Ist normalerweise Prozessorabhängig. Auf einer Intel CPU ist die
Reihenfolge: Low Byte liegt an der niedrigeren Adresse. Auf einer
Motorola CPU liegt das High Byte an der niedrigeren Adresse.
Sebastian B. wrote:
> ich arbeite im Automotive Bereich, da sind Unions aus> Sicherheits-/Portierungsgründen weitestgehend verboten (MISRA Regeln).
Siehs du, das verblüfft mich jetzt. Ich weiß, das in den MISRA Regeln
einige EInschränkungen gibt (weiß aber keine Details), aber die
schlimmste und gleichzeitig gefährlichste Waffe, die man in C haben
kann, den cast, darf man anscheinend machen. Mit einem Cast kann man so
ziemlich alles erreichen und ich hab da schon die wildesten Dinge
gesehen.
Interessenhalber: Gibts da irgendwelche Einschränkungen in MISRA welche
Casts zulässig sind und welche nicht?
Hi,
gut das du das ansprichst Karl Heinz. Ich kenne zwar die MISRA nit, aber
ich frage mich wirklich, was an nem Union so gefährlich sein soll,
gegenüber wildem casting und überflüssigen Maskierungen ?
Gruß und n8.
Karl heinz Buchegger wrote:
> Siehs du, das verblüfft mich jetzt. Ich weiß, das in den MISRA Regeln> einige EInschränkungen gibt (weiß aber keine Details),
siehe:
http://computing.unn.ac.uk/staff/cgam1/teaching/0703/misra%20rules.pdf>aber die> schlimmste und gleichzeitig gefährlichste Waffe, die man in C haben> kann, den cast,
Halt. Nicht der Cast ist gefährlich, sondern der implizite Cast!
Sowas hier:
1
Byte=i;/* impliziter cast */
den sollte man nicht verwenden!
43 (req): Implicit conversions that might result in a loss of
information shall not be used
>darf man anscheinend machen. Mit einem Cast kann man so> ziemlich alles erreichen und ich hab da schon die wildesten Dinge> gesehen.>> Interessenhalber: Gibts da irgendwelche Einschränkungen in MISRA welche> Casts zulässig sind und welche nicht?
Explizite sind zulässig, aber es ist nicht erlaubt Pointer auf einen
anderen Datentyp zu casten. Genauso wenig sind implizite Casts erlaubt.
45 (req): Type casting from any type to or from pointers shall not be
used
Zu Unions sagt MISRA auch etwas:
110 (req): Unions shall not be used to access the sub-parts of larger
data types
Abschliessend: Natürlich darf jeder so programmieren wie er mag, aber
(wie überall) gibt es in einem kritischen Umfeld eben auch gewisse
Regeln, die man befolgen sollte. Und sei es nur drum die lieben Kunden
zufrieden zustellen, damit die und wir ruhig schlafen / fahren können
:-)
Sebastian B. wrote:
>>aber die>> schlimmste und gleichzeitig gefährlichste Waffe, die man in C haben>> kann, den cast,>> Halt. Nicht der Cast ist gefährlich, sondern der implizite Cast!
:-)
Eine junge Kollegin (ist schon lange her), schrieb mal Folgendes
(sinngemäß)
1
structLine{intParams[10];};
2
structCircle{doubleRadius;};
3
4
structLine*Funktion(structCircle*circ)
5
{
6
...
7
return(structLine*)circ
8
}
und wunderte sich, warum das Program elendiglich verreckte. Nachdem sie
sich Hilfe geholt hatte, haben wir zu Dritt nach dem Fehler gesucht und
nach 2 Stunden dann diesen Bonmont entdeckt.
Ja das hätte sie als eine der letzten Aktionen gemacht. Und auf die
Frage, warum sie denn da überhaupt umgecastet hat, kam die Antwort: Weil
mir der Compiler eine Fehlermeldung gebracht hat, wenn ich den cast
weglasse.
Gefunden haben wir das nur deshalb, weil sie beim Aufrufer natürlich auf
die Struktur geschrieben hat, und sich auf diesem Wege den Returnstack
aber sowas von zerschossen hat. Wir sind beim Debuggen natürlich den
umgekehrten Weg gegangen: Progamm crasht, irgendwann verdichtete sich
der Gedanke, dass am Return Stack was nicht stimmt, und unzählige
Debuggerläufe später konnten wir den Bereich eingrenzen, an dem sich ein
paar Returnadressen am Stack seltsam verhielten :-)
Seitdem muss ich immer schmunzeln, wenn jemand einen cast als 'harmlos'
bezeichnet. (Klar: Schuld ist nicht der cast an sich, sondern sie hat
einfach nicht nachgedacht was sie da tut. Eine struct in eine komplett
andere struct umzucasten ist, wie wenn man ein Pferd für eine Kuh
verkauft)
> Explizite sind zulässig, aber es ist nicht erlaubt Pointer auf einen> anderen Datentyp zu casten. Genauso wenig sind implizite Casts erlaubt.
OK. So eingeschränkt ist das sinnvoll.
> Abschliessend: Natürlich darf jeder so programmieren wie er mag, aber> (wie überall) gibt es in einem kritischen Umfeld eben auch gewisse> Regeln, die man befolgen sollte.
Ja, das ist schon klar. Ich find das auch wichtig. So wie ich mich an
Regeln halte, erwarte ich auch von meinen Leuten dass sie sich an Regeln
halten. Ohne gehts nicht.
Muss ich mir doch mal reinziehen, dieses MISRA
Karl heinz Buchegger wrote:
> Sebastian B. wrote:>> Halt. Nicht der Cast ist gefährlich, sondern der implizite Cast!>> :-)
Ja, natürlich kann man mit Cast vielerlei Unfug generieren. ;-)
Diese MISRA Regel mit den explizisten Cast setzt natürlich voraus, dass
man weiss was man tut. Nicht unerheblich ist bei einem expliziten cast
natürlich auch der Nutzen der Dokumentation. Man SIEHT einfach in was
konvertiert werden soll. Wenn der Programmierer ganz gütig war hat er
vielleicht sogar noch einen Satz Kommentar dazu geschrieben.
>> Explizite sind zulässig, aber es ist nicht erlaubt Pointer auf einen>> anderen Datentyp zu casten. Genauso wenig sind implizite Casts erlaubt.>> OK. So eingeschränkt ist das sinnvoll.>>> Abschliessend: Natürlich darf jeder so programmieren wie er mag, aber>> (wie überall) gibt es in einem kritischen Umfeld eben auch gewisse>> Regeln, die man befolgen sollte.>> Ja, das ist schon klar. Ich find das auch wichtig. So wie ich mich an> Regeln halte, erwarte ich auch von meinen Leuten dass sie sich an Regeln> halten. Ohne gehts nicht.>> Muss ich mir doch mal reinziehen, dieses MISRA
Ich weiss natürlich auch nicht, ob MISRA DER WEG ist, aber zumindest
sind die Regeln anerkannt. Wenn man einem Kunden garantieren kann z.b.
mittels QA-C, dass man MISRA konform ist, dann werden schon mal ein paar
Anforderungen an die Software-Qualität abgedeckt. aber das ist ein
anderes Thema.. :-)