Frage an die C-Experten

Gast #5431
Lesenswert?
• ▲
▼
Ich möchte gerne die Feldinhalte eines u08 Feldes (erg8) in das nieder- 
und höherwertige Byte einer u16 Variablen (abc) bringen und das Ganze 
möglichst ohne zeitaufwendige Bitschiebereien. Dabei habe ich mir 
folgende Lösung ausgetüftelt (Beispiel):

typedef unsigned char u08;
typedef unsigned short u16;

int main(void)
{
        u16 *ptr16,abc;
        u08 erg8[1];

        ptr16 = &abc;
        erg8[0] = 0x55;
        erg8[1] = 0xaa;
        *((u08 *)ptr16+1) = erg8[1];
        *(u08 *)ptr16 = erg8[0];
}
Jedenfalls meckert mein Compiler dabei nichts an und auch ein Test mit 
einem Debugger unter Linux (gcc) zeigt keine "Unsauberkeiten" und, last 
but not least, es läuft und bringt das erwartete Ergebnis. Trotzdem habe 
ich bei diesem Code irgendwie ein ungutes Gefühl. Kennt jemand für diese 
Problematik eine bessere oder schönere Lösung? Ist der Code oben korrekt 
oder fällt das schon unter die Rubrik "unsaubere Tricks"?

Vielen Dank!

Gruss,

Peter
Gast #5433
Lesenswert?
• ▲
▼
Danke für die Auskunft, aber irgenwie bleiben doch noch Fragen offen.

> Die Bitschiebereien bei z.B. a=0xFF&(b>>8) werden von avr-gcc vollständig 
wegoptimiert.

Naja, so vollständig wird er sie ja nicht wegoptimieren ;-)
Schliesslich soll er hier ja noch etwas tun.

Ist mein Code denn wenigstens ok und gibt es vielleicht noch andere 
Ideen?

Gruss,

Peter
Gast #5434
Lesenswert?
• ▲
▼
Vorschlag:

#include <io.h>
#include <progmem.h>
#include <stdlib.h>


typedef union conv CONV;
union conv{
  struct{
    unsigned char s_[2];
  }s;
  unsigned short d;
};

static CONV  conv_local;
static unsigned short ergebnis;

int main(void)
{

  conv_local.s.s_[0] = 0x55;
  conv_local.s.s_[1] = 0xaa;

  ergebnis = conv_local.d;



}
Gast #5437
Lesenswert?
• ▲
▼
Hallo Matthias & Sebastian,

danke für den Tip mit dem union!

Manchmal sieht man den Wald vor Bäumen nicht ;-)

Das ist die elegante Lösung, nach der ich gesucht habe! Man könnte sogar 
noch auf dem selben Speicherplatz ein Bitfeld anlegen und so elegant auf 
die einzelnen Bits (bitte ein Bit!) zugreifen. C ist ja doch eine tolle 
Programmiersprache, sofern man sie beherrscht. Aber das schaffe ich 
eines Tages auch noch.

Gruss,

Peter
Gast #5438
Lesenswert?
• ▲
▼
was ist denn mit dieser variante:

int main(void)
{
u16 abc;
u08 erg8[1];

erg8[0] = 0x55;
erg8[1] = 0xaa;
abc = erg8[0] + (erg[1]<<8);
}

sollte doch zum selben ergebnis führen, oder?
Gast #5439
Lesenswert?
• ▲
▼
Wie sieht das eigentlich mit Felddeklarationen bei gcc aus?

 Im Ansi-C würde "u08 erg8[1];" nur ein Feld mit EINEM Eintrag (Index = 
0) erzeugen. Das ist doch mit gcc bestimmt nicht anders, oder?
Daraus würde dann folgen:

u08 erg8[2]; //mit Indizes 0 und 1

Falls einer eine gegesätzliche Auffassung hat, kann er das ja mal 
posten.

;-)
Gast #5440
Lesenswert?
• ▲
▼
@Dirk

Ich habe mich in meinem Code oben vertan. Es muss natürlich ein Feld mit 
2 Elementen deklariert werden, also

u08 erg8[2];

Somit kann man auf erg8[0] und erg8[1] zugreifen. Übrigens ein Fehler, 
der in C gerne von Anfängern gemacht wird, womit ich mich hier mal 
wieder verraten habe ;-)

@Jonas

natürlich kann man das so auch schreiben. Ich fand es nur etwas 
unelegant, das ist alles.

Gruss,

Peter
Gast #5442
Lesenswert?
• ▲
▼
Wieso nur eine Zeile? Wenn ich z.B. ein union definiere, brauche ich 
überhaupt nichts mehr zu transferieren, also nach Deiner Rechnung wären 
das dann null Zeilen, sowas finde ich z.B. eleganter!

mit :-) Gruss

Peter
Gast #5445
Lesenswert?
• ▲
▼
@Andreas
Du lässt einfach nicht locker ;-)

Dabei muss es, wenn schon mit Bitschieberei und Makro so heissen:

#define HIGH_BYTE(x) (0xFF&(x<<8))

Ok, ich frage ganz einfach meine Lebensgefährtin was ihr besser gefällt. 
Die hat zwar keine Ahnung von C, dafür weiss sie jedoch immer alles 
besser und hat letztendlich doch immer Recht ;-)

Gruss,

Peter
Gast #5446
Lesenswert?
• ▲
▼
> Lebensgefährtin [...] hat letztendlich doch immer Recht ;-)
Na dann bist du wohl auch nicht erstaunt, daß sie Andreas' Lösung 
favorisiert, oder?!

(Es soll ja das Highbyte zurückgeliefert, und nicht eines generiert 
werden, oder?)

Ansonsten:
> #define HIGH_BYTE(x) (0xFF&(x<<8))
Bei deinem Ansatz wäre das Ergebnis immer 0. Besser:
#define HIGH_BYTE(x) (x<<8)

Schmittchen.
Gast #5448
Lesenswert?
• ▲
▼
@Andreas: Auf was bezieht sich:
> Das funktioniert doch beides nicht.  ?

Ich war mir nicht sicher, was die Ursprungsfrage eigentlich war:
a.) Es soll das Highbyte zurückgegeben werden, dann gilt:
> Andreas' Lösung favorisiert
(also deine Lösung (Andreas) sollte stimmen)

oder b.) Es soll ein Highbyte generiert werden - um am Ende dann 
zusammen mit einem (Low)Byte ein 16Bit-Wert zu repräsentieren:
> #define HIGH_BYTE(x) (x<<8)
(setzt natürlich voraus, daß x als 16Bit-Variable deklariert ist... 
achso, eben hab ich dich verstanden: Wenn er es schon als 16Bit-Variable 
deklarieren muß, dann braucht die 2 8Bit-Variablen im Nachhinein nicht 
mehr zusammen zu tricksen.)

Aus Peters letzter Antwort war nicht eindeutig erkennbar, was er 
eigentlich will. In seinem ersten Posting klang das alles mehr nach 
generieren eines 16Bit-Wertes aus 2 8Bit-Werten.

Schmittchen, leicht verwirrt.
Gast #5450
Lesenswert?
• ▲
▼
@Andreas

Du hast Recht, die Bits müssen natürlich nach rechts geschoben werden. 
Und das Ausmaskieren kann man sich natürlich auch sparen. Also so sollte 
es dann richtig heissen:

#define HIGH_BYTE(x) (x>>8)

ok?

Sehrwahrscheinlich sind das noch so Erinnerungsfragmente, wo ich mal an 
little-Endian Systemen programmiert hatte. Ich glaube, da war das alles 
irgendwie anders herum.

Gruss,

Peter

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.