C Programmierung, 2 Variablen zu einer verbinden

Gast #2919177
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.
Persönliche Seite #2919200
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!
#2919278
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?????
Moderator Persönliche Seite #2919287
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.
Persönliche Seite #2919294
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.
Gast #2919304
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.
Gast #2919327
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"...
Moderator #2919347
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.
Gast #2919380
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren