Forum: Mikrocontroller und Digitale Elektronik Zusammenfügen von 2 mal 8 bit zu einem 16 bit Wert funktioniert nicht richtig


von Attila C. (attila)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich habe hier ein IMU was laut Datenblatt dies ausspuckt: "16-bit 2's 
complement integers"

Ich benutze diesen Wert um den 16bit Timer im CTC Mode von einem Atmega 
8 anzusteuern.
Hier das "Konstrukt":

yupper=receive();  // Pitch "grösseres" Byte
ylower=receive();  // Pitch "kleineres" Byte
          //yupper=255;
          //ylower=255;

y=((int16_t)yupper<<8)|ylower;    // Aus 2 8bit ein 16bit

ocr[1]=y;

Die "Symptome" sehen so aus:

-Setze ich yupper und oder ylower selber wie im Kommentar oben als 
Beispiel mit jeweils 255 sieht das auf dem Oszi so aus wie es soll.
-benutze ich nur yupper oder ylower die aus dem UART ausgelesen werden 
(receive) und setze den jeweils anderen wert selber sieht das Ergebnis 
auch gut aus.
-benutze ich aber beide empfangenen Werte sieht das (gefühlt) aus wie 
ein permanenter Überlauf beim bewegen des IMU.

Der Vollständigkeit halber das ist das gesammte Programm angehängt. Und 
wie immer schon mal vielen Dank!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?


von Attila C. (attila)


Lesenswert?

Diesen Beitrag hatte ich bereits studiert auch einige andere zu dem 
Thema. (Beitrag "16 Bit Variable aus 2 8 Bit laden")
Leider klappt es nicht. Ich habe probeweise mal den cast weggelassen das 
funktionierte auch nicht.

Allerdings funktioniert das:

y=yupper*255+ylower;

Das KANN aber so nicht richtig sein. Wer von den Profis mag hier Licht 
ins Dunkel bringen?

von Peter II (Gast)


Lesenswert?

receive() liefer ein int also signed zurück, damit gibt es probleme bei 
schieben.

von Attila C. (attila)


Lesenswert?

Hallo Peter. Danke für den Hinweis. Allerdings verstehe ich ihn nicht. 
Magst Du das etwas genauer erläutern?

von Peter II (Gast)


Lesenswert?

Attila Ciftci schrieb:
> Hallo Peter. Danke für den Hinweis. Allerdings verstehe ich ihn nicht.
> Magst Du das etwas genauer erläutern?

es gab schon öfters probleme beim schieben wenn eine signed variabel 
beteiligt ist. Änder mal recieve so ab das es ein unsigned 
zurückliefert.

von Purzel H. (hacky)


Lesenswert?

>Allerdings funktioniert das:
>
>y=yupper*255+ylower;


... es sollten eher 256 sein. y=yupper*256+ylower;

von Attila C. (attila)


Lesenswert?

Jetzt bin ich baff!
@Peter: Das hat nicht geklappt!
@Zwoelf: Du hast recht und siehe da:

y=yupper*256+ylower;

macht den gleichen "Fehler" wie:

y=yupper<<8|ylower

Was läuft da über und warum?

von Fabian O. (xfr)


Lesenswert?

Mach die Variablen unsigned:
1
unsigned char yupper = 0;
2
unsigned char ylower = 0;
und den Cast auf int16_t nach außen:
1
y = (int16_t) ((yupper << 8) | ylower);
In Deinem Fall könntest Du den Cast sogar weglassen, weil y ja schon 
int16_t ist.

von Peter D. (peda)


Lesenswert?

upper muß signed sein, lower muß unsigned sein.
Ist upper auch unsigned, klappt es nur auf 16Bit-CPUs, nicht aber auf 
32Bittern.

von Peter II (Gast)


Lesenswert?

Fabian O. schrieb:
> y = (int16_t) ((yupper << 8) | ylower);

last mal den cast weg. da wird es doch wieder signed, außerdem wird in C 
immer mit 16 gerechnet damit ist dieser nicht notwendig.

von Attila C. (attila)


Lesenswert?

Danke Fabian. Geht leider auch nicht :-(

von Coder (Gast)


Lesenswert?

Das ist ein Paradebeispiel, warum Bit-Operation auf signed-Value 
verpönnt sind. Caste deine Werte explizit vorheit auf dein Zieldatentyp.

von dodido (Gast)


Lesenswert?

// convert negative two's complement values to native negative value:
int temp_value = (data > 0x7fff) ? data - (0xffff + 1) : data;

von Fabian O. (xfr)


Lesenswert?

Ich schätze mal, Dein Problem liegt wo anders. Du schreibst den Wert ja 
letztlich in das OCR1A-Register. Da machen negative Werte aber keinen 
Sinn. Vielleicht willst Du zuerst noch prüfen, ob der gelieferte Wert 
größer/gleich Null ist bzw. auf einen positiven Bereich skalieren?

von Coder (Gast)


Lesenswert?

PS:

Bei Signed Werten: Beachte beim shiften immer das Vorzeichen!

von Attila C. (attila)


Lesenswert?

Vielen Dank für die Hinweise ich glaube das Problem liegt tatsächlich 
ganz wo anders:

Zuallerst mal: Ich habe mich bislang nicht so sehr darum gekümmert ob 
etwas signed ist oder nicht da ich erstmal nur möchte das das IMU mit 
mir spricht und sobald es das tut erstmal nur eine Neignung nach Rechts 
betrachten möchte.

Mulitpliziere ich mit 255 passiert auch ungefähr was passieren soll. 
Kippe ich das IMU nach rechts habe ich einen Peak von 6-7 ms länge und 
nach links von 40-800µs.

Ich habe probeweise den Wert von y fix vorgegeben. Wenn es kleiner ist 
als 0x0037 "spinnt" der µC was aber meines Erachtens auch richtg ist.

Bei Multiplikation mit 256 und auch bei der shift konstruktion kann ich 
auf meine Oszi sehen wie 8 bit durchlaufen werden und bei kleiner als 
0x37 der Timer "spinnt"

Mir ist das ein Rätsel, vielleicht hilft diese Beschreibung des Problems 
mehr.

von Attila C. (attila)


Lesenswert?

Ach so: Die 8 bit werden immer wieder durchlaufen bei einer konstanten 
Drehung des IMU

von Fabian O. (xfr)


Lesenswert?

Peter Dannegger schrieb:
> upper muß signed sein, lower muß unsigned sein.
> Ist upper auch unsigned, klappt es nur auf 16Bit-CPUs, nicht aber auf
> 32Bittern.

Eher im Gegenteil:
1
int receive (void)        //Funktion um ein Zeichen vom UART zu empfangen
2
{
3
  while (!(UCSRA&(1<<RXC)))   //Die Schleife prüft ob das Empfangsbit gesetzt ist
4
  ;                // ist es nicht gesetzt passiert nix.
5
  return UDR;          //Empfangenes Zeichen wird zurückgegeben
6
}
7
8
int main (void)
9
{
10
  int yupper=0;
11
  unsigned int ylower=0;
12
  int y;
13
14
  // ...
15
  yupper=receive();  // Pitch "grösseres" Byte 
16
  ylower=receive();  // Pitch "kleineres" Byte
17
  y=(yupper<<8)|ylower;
18
  // ...
19
}
Das funktioniert nur auf 16-Bit-Plattformen, nicht auf 32 Bit.

von Attila C. (attila)


Lesenswert?

Nach einer Weile des Nachdenkens:

"yupper" scheint immer 0 zu sein beim Shiften wie auch beim 
Multiplizieren mit 256. Bei Multiplikation mit 255 aber nicht. Was kann 
das sein?

von Fabian O. (xfr)


Lesenswert?

Erklär doch mal, was das Programm überhaupt machen soll. Diese 
Statemaschine in der Timer-ISR mit Neuladen des OCR1A-Register sieht mir 
ziemlich suspekt aus ...

Also:
- Welchen Wertebereich liefert der Sensor (laut Datenblatt) bei welcher 
Position?
- Was soll bei welcher Position bzw. welchem Wert passieren?

Am besten wäre, wenn Du erstmal sicherstellst, was da überhaupt für 
Zahlen ankommen. Hast Du irgendeine Möglichkeit, die Zahl menschenlesbar 
auszugeben, z.b. über die TX-Leitung des UART?

Wenn nicht, dann mach das Programm erstmal so einfach wie möglich. 
Schreib den empfangenen Wert direkt in OCR1A und lass den Timer einen 
Pin toggeln. Auf dem Oszi kannst Du dann anhand der Frequenz auf den 
Wert schließen.

von W.S. (Gast)


Lesenswert?

Attila Ciftci schrieb:
> y=((int16_t)yupper<<8)|ylower;    // Aus 2 8bit ein 16bit

Attila Ciftci schrieb:
> Nach einer Weile des Nachdenkens:

Oh nein.
IHR ALLE !!!! habt überhaupt nicht nachgedacht und stattdessen 
verzweifelt in der Gegend herumgecastet. Einer schöner als der andere.

Also: Casten ist mal ganz salopp gesagt etwa so, daß man dem Compiler 
sagt "Das soll jetzt aber mal ein ... sein."
Also zum Beispiel
if((unsigned long)MyPointer >= 0xA0100000) {.....}

Also: dein yupper ist und bleibt das was es ist, nämlich 8 Bit. An den 
Daten selbst kannst du nämlich durch Casten nix ändern.

Guck dir mal den entstandenen Code an oder probiere es mal ohne cast:

y = yupper;
y = (y<<8) | ylower;

Falls dein y ne lokale variable ist, steht sie ohnehin in einem Register 
und falls nicht (und auch nicht volatile), hofft man, daß der Compiler 
sich das Zwischenspeichern einspart.

W.S.

von Attila C. (attila)


Lesenswert?

Hallo W.S.:

Das hier ALLE falsch liegen ist recht unwahrscheinlich auch wenn die 
Vorschläge, genau so wie deiner, nicht das gewünschte Ergebnis 
erbrachten.

Fabian:

Ich habe deinen Vorschlag umgesetzt im Ergebnis bleib alles beim Alten. 
Allerdings wurde die Fehlersuche vereinfacht da ich zumindest keine ISR 
hatte die rumspinnt.

Ich habe das Rätsel dennoch im Trial und Error Verfahren gelöst und 
bitte um Rat der Profis:

Ich habe versuchsweise die Optimierung , die auf -Os war ausgeschaltet 
und siehe da: "y=(int16_t)((yupper<<8)|ylower)" bring das gewünschte 
Ergebnis.

An die Profis: Wie muss/soll ich das in Zukunft machen? -Os habe ich nur 
benutzt

1) Weil vor einiger Zeit die Ansteuerung eines Displays ohne optimierung 
nicht ging

2) Weil in diesem Artikel 
http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung die 
Optimierung -Os empfohlen wird.

Was ist das korrekte Verfahren?

von Dummschwaetzer (Gast)


Lesenswert?

nimmst du ein union!

von Attila C. (attila)


Lesenswert?

@Dummschwätzer:

Ist dein Alias Programm? Ich kann nämlich mit deiner Aussage nichts 
anfangen.

Ich bin in meinem C Buch noch nicht so weit fortgeschritten das ich 
wüsste was ein "union" ist.

von Dummschwaetzer (Gast)


Lesenswert?

Welches C-Buch? In der Regel im Kapitel Strukturen, unions, 
Aufzählungen. Siehe auch Register oder Inhaltsverzeichnis des Buches.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dummschwaetzer schrieb:
> nimmst du ein union!

Was hat das mit dem Problem zu tun?  Das bring bestenfalls neue Probleme 
(undefined behavior etc.)  Dies Forum ist voll mit Erklärungen und 
Hinweisen, warum.

von Dummschwaetzer (Gast)


Lesenswert?

Bei dem pillepalle kann man mit einer union nicht viel falsch machen, es 
soll ja nur int und char[2] übereinanderliegen.

von holger (Gast)


Lesenswert?

>Bei dem pillepalle kann man mit einer union nicht viel falsch machen, es
>soll ja nur int und char[2] übereinanderliegen.

Mit Kanonen auf Spatzen schiessen;)

Aus int receive (void) macht er ganz schnell mal
uint8_t receive (void). Warum? Ein UART überträgt 8Bit.
Der weiss einen Scheiss von signed, das ist dem sowas von egal.

Somit sind dann auch

  int yupper=0;
  int ylower=0;

als signed Variablen ganz schlecht gewählt.

  uint8_t yupper=0;
  uint8_t ylower=0;

Dann noch die Variante aus dem von Johann als erstes
gepostetem Link:

y = (int16_t)(((uint16_t)yupper << 8) + ylower);

Und alles sollte in Ordnung sein.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Der Hase wird irgendwo da im Pfeffer liegen, wo die Daten für 'y' 
erzeugt werden (vermutlich hat das was mit receive(..) zu tun), so dass 
der Zugriff auf 'y' bei jeder eingeschalteten Optimierung wegoptimiert 
werden wird. Irgendwas vernalasst den Compiler anzunehmen, dass sich 
'ylower' und 'yupper' niemals ändern.

von Attila C. (attila)


Lesenswert?

@Dummschwätzer:

-C von Helmut Erlenkötter

-Ich bin noch nicht mal im Kapitel 9 (Der Präprozessor) angekommen. Das 
union befindet sich im Kapitel 14 (Komplexe Datentypen) Es wird also 
noch ein weilchen dauern.

-Wer mag denn mir nun vorsagen was zu tun ist bis ich kapiert habe was 
die Optimierung genau bedeutet und macht?

Keine Optimierung?

Eine bestimmte Optimierung?

Oder egal, hauptsache es läuft, ausprobieren welche läuft?

Vielen Dank

Ach ja: Was dem einen pillepalla ist für den anderen schon recht 
kompliziert.

von holger (Gast)


Lesenswert?

>-Wer mag denn mir nun vorsagen was zu tun ist bis ich kapiert habe was
>die Optimierung genau bedeutet und macht?

Hast du meinen Post gelesen?

Hör auf für jeden Mist signed Variablen zu nehmen.
Schiebe und verodere signed Variablen besser nicht.
Dann ist es Wurst welche Optimierung du nimmst.

von Attila C. (attila)


Lesenswert?

@holger: Ich hatte zwischendurch für yupper und ylower unsigned char 
genommen das hat aber auch nichts gebracht. Genau genommen sehe ich es 
in meinem Anfänger-leichtsinn ähnlich wie du: Da werden 8 bit 
ausgespuckt (UART) und ob die signed sind oder nicht ist erstmal völlig 
wurscht.

@Patrick: Die Funktion receive kannst Du Dir gerne in der Codeansicht in 
meinem ersten Posting ansehen. Ich persönlich wüsste nicht wo da jetzt 
ein Problem sein sollte? Ich habe spasseshalber mal andere Optimierungen 
ausprobiert und bei manchen lief es und bei anderen nicht (Hab es nicht 
mehr so genau im Kopf)

Vielleicht hilft der nochmalige Hinweis: "yupper*255" brachte das 
gewünschte Ergebnis, "yupper<<8" nicht (Bei optimierung -Os)

Es läuft ja jetzt ohne Optimierung. Es bleibt die Frage: Wie gehe ich 
damit in Zukunft um?

von Attila C. (attila)


Lesenswert?

@Holger: Alles klar! Ich werde das ausprobieren. Unsere Posts hatten 
sich überschnitten!

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Ich muss gestehen: ich habe gerade erst in das im Eingangspost 
angehängte Sourcefile geguckt:

Du darfst natürlich nur Zuweisungen mit receive() machen, wenn Du 
tatsächlich Daten empfangen hast. Ansonsten passiert nämlich nicht 
'nichts' (wie in dem Kommentar erklärt), sondern 'return UDR;' gibt "0" 
zurück.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Quatsch! Falsch gelesen...

von Attila C. (attila)


Lesenswert?

@Holger:

Ich hab das jetzt genau so gemacht wie Du es vorgeschlagen hast. Leider 
klappt das nicht.

Und zwar sind jetzt yupper, ylower, und receive() uint8_t.

Dies:

y = (int16_t)(((uint16_t)yupper << 8) + ylower);

läuft nur bei ausgeschalteter Optimierung.

Dies:

y=(int16_t)((yupper<<8)|ylower);

läuft bei -O0, -O2, -O3 aber nicht bei -O1 und -Os

von Attila C. (attila)


Lesenswert?

Ich habe jetzt nochmal zum Ausprobieren yupper,ylower und receive() als 
int deklariert.

Jetzt laufen beide Varianten also:

y=(int16_t)((yupper<<8)|ylower);
und
y = (int16_t)(((uint16_t)yupper << 8) + ylower);

mit: -O0 -O2 und -O3

Aber nicht mit: -O1 und -Os

Ich habe den Eindruck das das Deklarieren der Variablen als signed oder 
unsigned hier nicht die Wurzel des Übels ist.

von holger (Gast)


Lesenswert?

>Ich hab das jetzt genau so gemacht wie Du es vorgeschlagen hast. Leider
>klappt das nicht.

Ich denke das dein Problem die ganzen signed Sachen sind.
OCR1A interessiert sich einen Scheiss für signed,
genau wie der UART. Und ocr[] ist auch unsigned.
Wieso muss y dann ein int16_t sein?

von Fabian O. (xfr)


Lesenswert?

holger schrieb:
> Wieso muss y dann ein int16_t sein?

Weil sein Sensor einen signed-Wert liefert, siehe allerersten Satz im 
ersten Post:
> Ich habe hier ein IMU was laut Datenblatt dies ausspuckt: "16-bit 2's
> complement integers"

@Attila: Poste mal den aktuellen Code.

von Attila C. (attila)


Lesenswert?

Weil ich mit y noch weiterrechne was übrigens auch sehr gut klappt.

von Attila C. (attila)


Lesenswert?

Ich habe es grade ausprobiert. Alles uint_8 repektive u_int16t. Es 
klappt nicht.Bei -Os. Ohne Optimierung läuft es. Einziger Unterschied 
ist das die Rechnung mit y nicht mehr so ist wie gewünscht. 
(Logischerweise)

von Maik M. (myco)


Lesenswert?

Bei welchem AVR ist eigentlich OCR1A & OCR1B 16Bit breit? Sicher, dass 
das stimmt? Das würde jedenfalls erklären weshalb die Multiplikation mit 
255 zu gehen scheint, aber mit 256 nicht (niederwertiges Byte ist da 
immer 0)

von Attila C. (attila)


Angehängte Dateien:

Lesenswert?

Es ist ein Atmega8. Ich fahre ein Modelbauservo an (daher y+14300 ergibt 
ungefähr 1,5 ms Mittelstellung des Servos) Sieht recht hübsch aus! Anbei 
wie gewünscht der aktuelle Code

von Maik M. (myco)


Lesenswert?

Beim Atmega8, sind OCR1A&OCR1B 8Bit, dein Fehler liegt also an einer 
ganz anderen Stelle

von Attila C. (attila)


Lesenswert?

Seite 76 das Atmega8 Datenblatts, Zitat:

"The 16-bit Timer/Counter unit allows accurate program execution timing 
(event management),
wave generation, and signal timing measurement. The main features are:
• True 16-bit Design (i.e., allows 16-bit PWM)"

Ausserdem läuft es ja ohne Optimierung ich kann mir die 16bit Auflösung 
sogar auf dem Oszi anschauen.

von Attila C. (attila)


Lesenswert?

Der Vollständigkeit halber, Seite 79:

"The TCNT1, OCR1A/B, and ICR1 are 16-bit registers......."

von Attila C. (attila)


Lesenswert?

Ach so Fabian, Du fragtest auch mal nach dem Sensor. Es ist ein CHR6-dm.

von Maik M. (myco)


Lesenswert?

hab wohl A/B mit L/H verwechselt...

von Attila C. (attila)


Lesenswert?

@Maik: Ach so! Ich war schon etwas verunsichert jetzt. Naja, sowas 
pasiert!

von Fabian O. (xfr)


Lesenswert?

Bei Deinem letzten Code sehe ich jetzt keine Fehlerquellen mehr. Solange 
die Werte des Sensors zwischen -14300 und 18467 liegen, sollte es keine 
ungewöhnlichen Sprünge/Überläufe geben.

Welche Compilerversion benutzt Du denn? Vor ein paar Wochen gabs mal ein 
ähnliches Thema, da war es letztlich ein Fehler im avr-gcc aus 
AVR-Studio 5.

von Attila C. (attila)


Lesenswert?

Ok auf die Gefahr hin dass ich hier geschlachtet werde: Wo kann ich beim 
Studio5 ersehen welche Compilerversion ich habe?

von Fabian O. (xfr)


Lesenswert?

Im Studio 6 steht es unter Help -> About Atmel Studio und da im Dropdown 
AVRGCC. Aber der Hinweis auf Studio 5 reicht eigentlich schon. Versuchs 
mal mit Studio 6 oder zumindest der aktuellen Version der Toolchain.

von Attila C. (attila)


Lesenswert?

Ok, auch wenn das etwas off topic ist jetzt: Unterstützt das Studio 6 
denn das STK500?

Mein AVRGCC hat die Version 3.3.1.27 wie ich anhand deiner Anleitung 
herausfinden konnte.

von Fabian O. (xfr)


Lesenswert?

Attila Ciftci schrieb:
> Ok, auch wenn das etwas off topic ist jetzt: Unterstützt das Studio 6
> denn das STK500?

Sollte gehen.

> Mein AVRGCC hat die Version 3.3.1.27 wie ich anhand deiner Anleitung
> herausfinden konnte.

Das dürfte das Problem sein. Siehe hier:
Beitrag "Umwandlung von zwei uint8_t in uint16_t erzeugt falschen Code?"

Ach ja, weil ich gerade gelesen habe, dass Du einen Modellbauservo 
ansteuerst: Das geht mit dem 16-Bit-Timer ganz ohne Interrupt. Du musst 
einfach den Top-Wert so einstellen, dass die Periode 20 ms beträgt. Dann 
reicht es, in das Compare-Register 1/20 bis 1/10 des Top-Werts als 
Duty-Cycle reinzuschreiben. Von der Auflösung her sollte das dank 16 Bit 
genau genug für einen Servo sein.

von Attila C. (attila)


Lesenswert?

Oh wow! Jetzt wird mir einiges klar. Ich wäre allerdings nie darauf 
gekommen nach so einem Fehler im Forum zu suchen. Wie soll man denn auf 
so etwas kommen?

Ich lade mir mal das Studio 6 runter.

Klar im Moment läuft es ja auch ohne interrupt. Die state maschine in 
meiner ISR soll aber bis zu 7 Servos steuern. Irgendwann. Mal sehen. Auf 
jeden Fall:

Vielen Dank für die Hilfe!!!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Der mögliche Fehler hat die Nummer PR46779.

Er ist behoben in 4.5.4, 4.6.2 und neueren Versionen.  Und das ist die 
GCC-Version, nicht die "Atmel-Version".

Die GCC-Version wird angezeigt mit

avr-gcc --version

von Hmmm (Gast)


Lesenswert?

Johann L. schrieb:
> Er ist behoben in 4.5.4, 4.6.2

Und wie kommt man an die Versionen für Windows feertig einsetztbar? Ich 
meine ohne sich das Zeug selber zu kompilieren?

Danke

von Peter II (Gast)


Lesenswert?

Hmmm schrieb:
> Und wie kommt man an die Versionen für Windows feertig einsetztbar? Ich
> meine ohne sich das Zeug selber zu kompilieren?

einfach bei Atmel downloaden (nennt sich toolchain). Dann bekommt man 
zumindest die 4.6.2

von Dummschwaetzer (Gast)


Lesenswert?

Helmut Herold: C Compakt Referenz
ISBN 3-8273-1480-1, 1.Auflage 1999
Kapitel 2.41 auf Seite 122, für dich interessant: 2.41.2 Overlay-Technik 
... Seite 124f

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Dummschwaetzer schrieb:
> Welches C-Buch? In der Regel im Kapitel Strukturen, unions,
> Aufzählungen. Siehe auch Register oder Inhaltsverzeichnis des Buches.

Dummschwaetzer schrieb:
> Helmut Herold: C Compakt Referenz
> ISBN 3-8273-1480-1, 1.Auflage 1999
> Kapitel 2.41 auf Seite 122, für dich interessant: 2.41.2 Overlay-Technik
> ... Seite 124f

Wenn das wirklich meint: Byte-Komponenten setzen und lesen einer 16-Bit 
Variablen aus der Union, dann entsorg das Buch zum Altpapier.

Der C-Standard sichert nur zu, die zuletzt geschriebene Komponente einer 
Union auch wieder auszulesen. Alle anderen Komponente der Union erhalten 
durch Zuweisung undefinierte Werte (mit Ausnahme eines ersten, allen 
Komponenten gemeinsamen Elements, i.d.R Verwendnet zur Identifikation 
des Union-Inhalts).

Konkret: In
1
unsigned compose (char a, char b)
2
{
3
    union
4
    {
5
        char byte[2];
6
        unsigned word;
7
    } u;
8
    
9
    u.byte[0] = a;
10
    u.byte[1] = b;
11
    
12
    return u.word;
13
}
Wird die Komponente .word nie geschrieben. Ein Konformer Compiler darf 
das also genau so übersetzen wie:
1
unsigned compose (char a, char b)
2
{
3
    unsigned word;
4
    
5
    return word;
6
}

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.