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


von Simon (Gast)


Lesenswert?

Ich habe zwei einzelne Byte und moechte nun ein 16 bit int draus machen.


sowas gibts bei ADCL und ADCH z.B.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi
1
uint16_t u16;
2
uint8_t u8_low;
3
uint8_t u8_high;
4
5
u16 = u8_high * 256 + u8_low;

Matthias

von Michael M. (Gast)


Lesenswert?

uint16_t make_u16(uint8_t high_byte, uint8_t low_byte)
{
  return ( ((uint16_t)high_byte)<<8 | low_byte)
}

von Simon (Gast)


Lesenswert?

Danke,

aber so einfach?

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

von R. F. (rfr)


Lesenswert?

Verwende eine union.
Gruss
Robert

von Michael M. (Gast)


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...

von Simon (Gast)


Lesenswert?

würde eine Union so aussehen?

union u16 { char a; char b;} ;

von nicht "Gast" (Gast)


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;

von nicht "Gast" (Gast)


Lesenswert?

aber bedenke, das einfachste wurde schon von matthias und ad-rem 
genannt...

von Pete K. (pete77)


Lesenswert?

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

von Klaus W. (mfgkw)


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:
1
uint16_t   ergebnis;
2
uint8_t    daseinebyte, dasanderebyte;
3
...
4
((uint8_t*)&ergebnis)[0] = daseinebyte;
5
((uint8_t')&ergebnis)[1] = dasanderebyte;

von Michael M. (Gast)


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.

von nicht "Gast" (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


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.

von Simon K. (simon) Benutzerseite


Lesenswert?

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

von Nils S. (kruemeltee) Benutzerseite


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?

von Michael M. (Gast)


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.

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Dann eben:

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

;)

von Hc Z. (mizch)


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.

von Michael M. (Gast)


Lesenswert?

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

von Hc Z. (mizch)


Lesenswert?

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

von Reiner (Gast)


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

von Michael M. (Gast)


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).

von Simon K. (simon) Benutzerseite


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.

von Hc Z. (mizch)


Lesenswert?

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

Na, an Michael selbstverständlich.

von Karl H. (kbuchegg)


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.

von Hc Z. (mizch)


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.)

von Michael M. (Gast)


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?

von Michael M. (Gast)


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 ^^

von Karl H. (kbuchegg)


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.

von Michael M. (Gast)


Lesenswert?

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

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.