www.mikrocontroller.net

Forum: Compiler & IDEs 2 byte in ein 16 bit int


Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe zwei einzelne Byte und moechte nun ein 16 bit int draus machen.


sowas gibts bei ADCL und ADCH z.B.

Autor: Μαtthias W. (matthias) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
uint16_t u16;
uint8_t u8_low;
uint8_t u8_high;

u16 = u8_high * 256 + u8_low;

Matthias

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint16_t make_u16(uint8_t high_byte, uint8_t low_byte)
{
  return ( ((uint16_t)high_byte)<<8 | low_byte)
}

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke,

aber so einfach?

gabs da nicht was mit bit shift << >> ?

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verwende eine union.
Gruss
Robert

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
binärsystem:
x*(2^1) == x<<1
x*(2^2) == x<<2
x*(2^3) == x<<3

dezimalsystem:
x*(10^1) == x<<1
usw...

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
würde eine Union so aussehen?

union u16 { char a; char b;} ;

Autor: nicht "Gast" (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon schrieb:
> würde eine Union so aussehen?
>
> union u16 { char a; char b;} ;

nein, eher so:

union blah {
    uint16_t als_int;
    struct {
        uint8_t ein_byte;
        uint8_t nochn_byte;
    } als_bytes;
};


union blah test;
test.ein_byte = 0x42;
test.nochn_byte = 0x23;

uint16_t irgend_nen_int = test.als_int;

Autor: nicht "Gast" (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber bedenke, das einfachste wurde schon von matthias und ad-rem 
genannt...

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist IMHO nicht garantiert, dass in einer union die Variablen auf 
fortlaufenden Speicheradressen abgebildet werden. Hängt vom Compiler ab.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wobei shiften und multiplizieren nicht besonders effizient sind,
wenn es öfter gemacht wird.

Schneller ist die Geschichte mit der union.

Falls es schnell gehen soll und die union zu unpraktisch erscheint,
dann geht es auch so:
uint16_t   ergebnis;
uint8_t    daseinebyte, dasanderebyte;
...
((uint8_t*)&ergebnis)[0] = daseinebyte;
((uint8_t')&ergebnis)[1] = dasanderebyte;

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> wobei shiften und multiplizieren nicht besonders effizient sind,
> wenn es öfter gemacht wird.
so? shift und oder hat der avr in hardware. das geht auch in 16bit 
schnell.

Autor: nicht "Gast" (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
pete77 hat auch was wichtiges gesagt, bei gcc sollte man deswegen auch 
das ganze mit __attibute__((packed)) machen...

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pete K. schrieb:
> Es ist IMHO nicht garantiert, dass in einer union die Variablen auf
> fortlaufenden Speicheradressen abgebildet werden. Hängt vom Compiler ab.

Die Elemente einer union sind eh nicht auf fortlaufenden Adressen,
höchstens die der struct.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Shift um 8 wird sowieso nicht direkt in Assemblercode umgesetzt. 
Union Methode und Shift Methode werden vermutlich genau gleich 
implementiert.

Autor: Nils S. (kruemeltee) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned char byteL, byteH;
unsigned short i;

i = (byteH << 8) + byteL;

> Die Elemente einer union sind eh nicht auf fortlaufenden Adressen,
> höchstens die der struct.
dafür gibts doch das Attribut packed, oder?

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nils S. schrieb:
> i = (byteH << 8) + byteL;
vorsicht, das muss nicht klappen! dein byteH musst du casten, sonst 
schiebst du aus deinem speicherbereich raus.
auf dem avr klappt das vermutlich, weil er bei einem shift um größer 7 
sowieso weiteren speicher braucht und der compiler den bereitstellt.
auf anderen architekturen muss das nicht so ein.

Autor: Nils S. (kruemeltee) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann eben:

i = ((unsigned short) byteH << 8) + byteL;

;)

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael M. schrieb:
> Nils S. schrieb:
>> i = (byteH << 8) + byteL;
> vorsicht, das muss nicht klappen! dein byteH musst du casten, sonst
> schiebst du aus deinem speicherbereich raus.

Da wird nach Standard C nichts "rausgeschoben" und muss nichts gecastet 
werden.  Und zwar gleich aus 2 Gründen, die der Standard vorgibt:

- der rechte Operand von << ist ein Integer, also muss das Ergebnis 
mindestens Integer sein

- kleinere Werte als int werden automatisch zu int (integer promotion), 
bevor sie verrechnet werden.  Über die Sinnhaftigkeit dieser Regel kann 
man sich bei so kleinen CPUs lange unterhalten und es gibt gute 
Argumente dagegen.  Ich habe eine gute Ausrede:  Es ist Vorschrift.

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hc Zimmerer schrieb:
> [käse]
sicher nicht auf dem avr-gcc...

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du wolltest den Beweis sicher antreten und hast nur vergessen, ihn 
anzuhängen.

Autor: Reiner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Michael M. schrieb
> > Hc Zimmerer schrieb:
> > [ käse]
> sicher nicht auf dem avr-gcc...

Hier sollte eine Quelle angegeben werden, falls der C-Standard von 
avr-gcc an dieser Stelle verletzt wird. Meines Erachtens ist's genauso, 
wie Hc schreibt. An was sollte sich ein C-Compiler denn bei der 
Auswertung von Ausdrücken halten?

Reiner

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
integer (16bit) promotion auf einer 8-bit architektur macht keinen sinn.
und der rechte operad vom shift ist kein int (16 bit integer), sondern 
ein char (8 bit integer).

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael M. schrieb:
> integer (16bit) promotion auf einer 8-bit architektur macht keinen sinn.
Ist aber trotzdem so bei dem AVR-GCC.

> und der rechte operad vom shift ist kein int (16 bit integer), sondern
> ein char (8 bit integer).
Zahlenkonstanten sind immer integers.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> An was sollte sich ein C-Compiler denn bei der
> Auswertung von Ausdrücken halten?

Na, an Michael selbstverständlich.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael M. schrieb:
> integer (16bit) promotion auf einer 8-bit architektur macht keinen sinn.
> und der rechte operad vom shift ist kein int (16 bit integer), sondern
> ein char (8 bit integer).

[ ] Du hast Ahnung davon, was der C-Standard von einem Compiler fordert
    damit er als C-Compiler gilt
[ ] Du weißt vielleicht nicht, dass C eine Sprachdefinition hat und
    nicht jeder dahergelaufene Compilerbauer seine Sprache so
    implementieren kann wie er möchte und das Ganze dann "C" nennen
    kann.
[ ] Du hast deinen K&R aufmerksam gelesen und festgestellt, dass in
    C zwar manches (vieles) dem Compilerbauer freigestellt ist, es aber
    trotzdem ein paar grundlegende Dinge gibt, an die er sich halten
    muss.

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael M. schrieb:
> integer (16bit) promotion auf einer 8-bit architektur macht keinen sinn.

Nicht alles, was der C-Standard vorschreibt, macht auf allen 
Architekturen Sinn (und ich habe die Sinnhaftigkeit auch erwähnt).  Die 
GCC-Familie inklusive avr-gcc hält sich daran.

> und der rechte operad vom shift ist kein int (16 bit integer), sondern
> ein char (8 bit integer).

Ein Buch über C hilft hier doch sehr, es muss nicht mal der Standard 
sein.  Das Literal "8" ist ein int.
__
(Und immer noch hast Du keinen Beweis geliefert, sondern nur weitere 
Behauptungen.)

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. schrieb:
> Michael M. schrieb:
>> integer (16bit) promotion auf einer 8-bit architektur macht keinen sinn.
> Ist aber trotzdem so bei dem AVR-GCC.
warum wird mein code dann größer, wenn ich beim typedef aus meinem 
int8_t ein int mache?

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hc Zimmerer schrieb:
>> An was sollte sich ein C-Compiler denn bei der
>> Auswertung von Ausdrücken halten?
>
> Na, an Michael selbstverständlich.
wär mir auch lieber ^^

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael M. schrieb:
> Simon K. schrieb:
>> Michael M. schrieb:
>>> integer (16bit) promotion auf einer 8-bit architektur macht keinen sinn.
>> Ist aber trotzdem so bei dem AVR-GCC.
> warum wird mein code dann größer, wenn ich beim typedef aus meinem
> int8_t ein int mache?

Das kann man erst beantworten, wenn man den Code sieht.
Auch wenn die C-Regeln grundsätzlich die int-Promotion vorsehen, heißt 
das noch lange nicht, dass ein Compiler sie nicht auch wieder rauswerfen 
darf, wenn er beweisen kann, dass sich durch den Wegfall der Promotion 
nach int nichts ändert.
Das heißt aber nicht, dass die int-Promotion grundsätzlich nicht gilt. 
Das heißt nur, dass ein Optimizer die eigentlich vorhandene Promotion 
weglassen kann, weil sie auf das Ergebnis keinen Einfluss hat.

Wenn der Optimizer sich die Sache ansieht und zb. feststellt, dass das 
Ergebnis in einer 8-Bit Variablen gespeichert wird, kann er den Code 
rückwärts verfolgen und alle High-Byte Manipulationen, die der 
eigentliche Compiler eingefügt hat, wieder rauswerfen, weil sie im 
Ergebnis nicht auftauchen.

Autor: Michael M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
alles klar. danke für die aufklärung.
da lag ich wohl daneben. entschuldigung.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.