Forum: Mikrocontroller und Digitale Elektronik C Programmierung, 2 Variablen zu einer verbinden


von Peter (Gast)


Lesenswert?

Hallo,
Hoffe kann mir einer hier weiterhelfen.

Ich will 2 Char Zahlen zu einer short verbinden, habs auch hinbekommen 
und so realisiert:
1
unsigned char a = 0x76;
2
unsigned char b = 0x02;
3
unsigned short c = (b << 8) | a ; //c= 0x276

Jedoch wird durch diese Methode zuviel Rechenlaufzeit benutzt. Kennt 
jemand vielleicht eine andere Möglichkeit ohne zu shiften diese 2 Zahlen 
zu einer zu verbinden.
Danke.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wenn ich diesen deinen Code in gültiges C umwandle
1
unsigned short ab (void)
2
{
3
    unsigned char a = 0x76;
4
    unsigned char b = 0x02;
5
    unsigned short c = (b << 8) | a ; //c= 0x276
6
    return c;
7
}

mit gcc übersetzt

$ gcc foo.c -O2 -S

macht er daraus
1
ab:
2
  pushl  %ebp
3
  movl  $630, %eax
4
  movl  %esp, %ebp
5
  popl  %ebp
6
  ret

Wenn dir CallFrame-Debugging nicht wichtig ist und du übersetzt mit

$ gcc foo.c -O2 -S -fomit-frame-pointer

wird es sogar zu
1
ab:
2
  movl  $630, %eax
3
  ret

Wenn das zu langsam ist, dann liegen deine Probleme ganz woanners!

von Jens M. (Gast)


Lesenswert?

Peter schrieb:
> Kennt
> jemand vielleicht eine andere Möglichkeit ohne zu shiften diese 2 Zahlen
> zu einer zu verbinden.

Mit einer union geht das ohne eine Rechenoperation, ist aber wegen 
big/little endian problem nicht portabel.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Jedoch wird durch diese Methode zuviel Rechenlaufzeit benutzt.
WIE hast du das festgestellt? WELCHEN Compiler hast du da verwendet?

> Kennt jemand vielleicht eine andere Möglichkeit ohne zu shiften
> diese 2 Zahlen zu einer zu verbinden.
Ja: dein Compiler.

von Peter (Gast)


Lesenswert?

ok, vielleicht täusche ich mich ja auch, sagen wir so, gibt es eine 
andere Methode als mit shiften, und High byte und Low byte, zwei char 
Variablen zu einer short zu verknüpfen. Danke.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Multiplikation. Allerdings ist ein Shiften auch nur ein Spezialfall 
einer Multiplikation.
1
unsigned short c = b * 256 + a;

von Jens (Gast)


Lesenswert?

>>gibt es eine andere Methode als mit shiften

sag mal Peter, pennst du? lies mal richtig...

"Mit einer union geht das ohne eine Rechenoperation"

JJ

von Peter (Gast)


Lesenswert?

Danke für die Antwort, das funktioniert, aber du hast recht, ist halt ne 
andere Form von shiften. Gibt es da eine Möglichkeit mit Arrays zusammen 
zufügen.

von Peter (Gast)


Lesenswert?

und wie funktioneirt das mit einer union, kenne ich nicht.

von Ralf G. (ralg)


Lesenswert?

Peter schrieb:
> ok, vielleicht täusche ich mich ja auch, sagen wir so, gibt es eine
> andere Methode als mit shiften, und High byte und Low byte, zwei char
> Variablen zu einer short zu verknüpfen. Danke.
1
00000048 <ab>:
2
{
3
    unsigned char a = 0x76;
4
    unsigned char b = 0x02;
5
    unsigned short c = (b << 8) | a ; //c= 0x276
6
    return c;
7
}
8
  48:  86 e7         ldi  r24, 0x76  ; 118
9
  4a:  92 e0         ldi  r25, 0x02  ; 2
10
  4c:  08 95         ret

noch schneller?????

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
>
1
> unsigned char a = 0x76;
2
> unsigned char b = 0x02;
3
> unsigned short c = (b << 8) | a ; //c= 0x276
4
>

Ich nehme mal an, dass Dein tatsächlicher Code NICHT so aussieht, denn 
das obige optimiert Dir der gcc zu

  c = 0x0276

Schneller gehts nicht.

Also jetzt mal Tacheles:

1. Welcher µC?
2. Welcher Compiler? Wirklich gcc?!?
3. Wie sieht Dein Quellcode tatsächlich aus?
4. Wieviel Rechenzeit wird verbraten?

Ohne die Beantwortung dieser Fragen ist weitere Hilfe unmöglich.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peter schrieb:
> und wie funktioneirt das mit einer union, kenne ich nicht.

Lies ein C-Buch.

Wirklich. Da drin steht, was eine union ist, und das musst Du, um es 
benutzen zu können, auch begreifen.

Deswegen bringen irgendwelche zusammenkopierten Codeschnipsel aus 
irgendwelchen "Tutorials" auch nichts.

Brian Kernighan & Dennis Ritchie, "Programmieren in C", 2. Ausgabe, 
Hanser-Verlag.

von xfr (Gast)


Lesenswert?

Ob Du da Multiplikation oder Shiften hinschreibst, ist egal. Der 
Compiler kümmert sich darum, dass das Ergebnis mit den zur Verfügung 
stehenden Maschinenbefehlen möglichst effizient erreicht wird. Nur weil 
im C-Code ein Shift da steht, wird daraus also nicht zwangsläufig auch 
ein Shift-Maschinenbefehl werden. Der Compiler kann also durchaus 
erkennen, was Du da vorhast, und kopiert einfach das Byte an die 
richtige Stelle.

Das ganze steht ja sowieso nicht für sich. Die Variablen liegen entweder 
im Speicher oder schon in CPU-Registern und das Ergebnis wird auch 
irgendwie weiterverarbeitet. Vielleicht muss dabei im Endeffekt nicht 
mal umkopiert werden, gerade wenn es ein 8-Bit-Prozessor ist.

Schreib den Code also so, dass man ihn gut versteht und lass den 
Compiler den Rest machen. Die Stelle ist garantiert kein 
Geschwindigkeitsengpass.

von Peter (Gast)


Lesenswert?

1. Stellaris LM3S9b96
2. ARM Yagarto GCC Compiler
3. so wie da oben, will nur variablen verknüpfen
4. ich glaube ich mach da einen Denkfehler

von Bronco (Gast)


Lesenswert?

Peter schrieb:
> Jedoch wird durch diese Methode zuviel Rechenlaufzeit benutzt.
Beweisen!

> eine andere Möglichkeit ohne zu shiften
Wie xfr richtig schreibt, bedeutet der Operator
[C]
(b << 8)
[C/]
nicht zwangsläufig, daß irgendjemand anfängt, irgendetwas zu schieben.
Du sagst dem Compiler damit:
"Interpretierte b um 8 Bits nach links geschoben"
Der Compiler kennt da mitunter tolle Tricks, wie z.B. den "SWAP"...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Der ARM shiftet gern. Er tut das lieber und schneller als auf das RAM
zuzugreifen, wie es bei der Union-Methode vermutlich der Fall wäre.

Probier doch einfach mal verschiedene Methoden aus und schau dir den
generierten Assemblercode an. Ich bin mir fast sicher, dass du keine
bessere als die Shift-Methode finden wirst, die zudem gut lesbar und
nicht von der Endianess abhängig ist.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Der gcc ersetzt Shifts von Variablen, die einen bekannten Wert haben 
(und die Variablen a und b in obigem Quellcode sind bekannt!) direkt 
durch eine Konstante. Der TO muss sich irren. Sein Problem muss woanders 
liegen.

von Jens M. (Gast)


Lesenswert?

Peter schrieb:
> und wie funktioneirt das mit einer union, kenne ich nicht.

Die union packt dir die beiden chars in Speicherzellen nebeneinander. 
Gleichzeitig entsteht daraus dann ein 2 byte Wert (z.B. uint) daraus.

Das braucht überhaupt keine Rechenoperation da die char Werte 
"strukturbedingt" einen int bilden.

Da aber die Compiler die int Werte in unterschiedlicher Bytereihenfolge 
abbilden (Lowbyter oder Highbyte zuerst) ist es nicht portabel.

von Ralf G. (ralg)


Lesenswert?

Jens Martin schrieb:
> Da aber die Compiler die int Werte in unterschiedlicher Bytereihenfolge
> abbilden (Lowbyter oder Highbyte zuerst) ist es nicht portabel.

War das nicht so, dass die CHARs auch mal fix an 32 od. 64 Bit 
ausgerichtet werden können?

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.