Forum: Compiler & IDEs 40 Bit in 5 Bytes abbilden mit Bitfeld


von Mathias G. (mgiaco)


Lesenswert?

Hallo,

Eine Frage ich Suche nach einer Möglichkeit 40 Bit in 5 Byte 
unterzubringen Das ist ja eigentlich sehr einfach :-), nur würde ich das 
gerne über ein C Bitfeld lösen.

Ich komme auf 8 Byte - was für mich auch klar zu erklären ist. Aber gibt 
es vielleicht einen Trick dem Compiler doch klar zu machen, das noch 
kompakter abzulegen.
1
  typedef struct
2
  {
3
    /* 2 byte */
4
    uint16_t status_display;
5
    /* 5 byte */
6
    uint16_t left1:5;
7
    uint16_t right1:5;
8
    uint16_t left2:5;
9
    uint16_t right2:5;
10
    uint16_t left3:5;
11
    uint16_t right3:5;
12
    uint16_t left4:5;
13
    uint16_t right4:5;
14
  }  __attribute__((gcc_struct)) tx_data;

Alternative wäre natürlich maskieren und schiften. Würdet ihr das auf 
einem 32Bit ARM generell vorziehen?

Danke.

von Karl (Gast)


Lesenswert?

Die Frage ist eher wozu das erforderlich ist. Es riecht hier evtl etwas 
nach Mikro Optimierung und das ist bekanntlich sch...

Wenn das für die Übertragung mit festgelegten Bit codierten Signalen ist 
dann würde ich schieben und verodern. Auf keinen Fall sollte dann ein 
Attribut erforderlich sein. Ein biteld geht in c auch ohne 
compilerspezifischen Murks.

von Mikro 7. (mikro77)


Lesenswert?

Mathias G. schrieb:
>
1
>   typedef struct
2
>   {
3
>     /* 2 byte */
4
>     uint16_t status_display;
5
>     /* 5 byte */
6
>     uint16_t left1:5;
7
>     uint16_t right1:5;
8
>     uint16_t left2:5;
9
>     /* erster uint16_t belegt, 1 bit unbenutzt */
10
>     uint16_t right2:5;
11
>     uint16_t left3:5;
12
>     uint16_t right3:5;
13
>     /* zweiter uint16_t belegt, 1 bit unbenutzt */
14
>     uint16_t left4:5;
15
>     uint16_t right4:5;
16
>     /* dritter uint16_t belegt, 6 bit unbenutzt */
17
>   }  __attribute__((gcc_struct)) tx_data;
18
>

Implementierung ist generell compilerabhängig.

> Alternative wäre natürlich maskieren und schiften. Würdet ihr das auf
> einem 32Bit ARM generell vorziehen?

Immer dann wenn du das genaue Bitlayout benötigst.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Mathias G. schrieb:
> Alternative wäre natürlich maskieren und schiften. Würdet ihr das auf
> einem 32Bit ARM generell vorziehen?

Ja. Selbst wenn Du es hinbekommst, dass Deine Bitfelder exakt Deine 
Datenstruktur abbilden: Die Datenkompaktheit ist compiler-abhängig, das 
Ganze ist nicht portabel und passt je nach Alignment des verwendeten µCs 
nur zufälltig. Aber das wichtigste: Um die Daten auseinanderzuklamüsern, 
muss der Compiler selbst auch maskieren und shiften. Es gibt also keinen 
echten Gewinn. Dann mach ich das lieber selbst und ich weiß, was ich 
habe.

von Markus F. (mfro)


Lesenswert?

nachdem das jetzt geklärt wäre, noch was anderes:

Mathias G. schrieb:
> }  __attribute__((gcc_struct)) tx_data;

... ich glaube nicht, daß das Attribut gcc_struct auf ARM irgendwas 
(geschweige denn, was Sinnvolles) tut. Das würd' ich weglassen.

von Peter D. (peda)


Lesenswert?

Mathias G. schrieb:
> Eine Frage ich Suche nach einer Möglichkeit 40 Bit in 5 Byte
> unterzubringen

Die Frage ist, wozu man sich das antun will?
Wenn es nur darum geht, RAM zu sparen, dann würde ich das sein lassen 
und einfach je 3 Bits verschenken.

Wenn es darum geht, externe 5-Bit Schieberegister abzubilden, dann würde 
ich dafür eine Funktion schreiben, die ein 8Byte-Array entsprechend aufs 
SPI ausgibt. Diesen Schrunz durch das ganze Programm zu ziehen, würde 
ich sein lassen.

Wenn es ein 5*8 Font werden soll, einfach um 90° gedreht abspeichern, 
also 5 Byte je Zeichen.

: Bearbeitet durch User
von Micha (Gast)


Lesenswert?

Hast Du dir mal sizeof(tx_data) angesehen?

Ich würde erwarten, dass entweder die Größe nicht deinen Erwartungen 
entspricht, oder aber Padding Bits an stellen sitzen, an denen Du sie 
nicht erwartest.

von Achim (Gast)


Lesenswert?

Micha schrieb:
> Hast Du dir mal sizeof(tx_data) angesehen?

Mathias G. schrieb:
> Ich komme auf 8 Byte

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Vielleicht hilft:
typedef __packed struct { };

: Bearbeitet durch User
von Volle (Gast)


Lesenswert?

dafür gibt es das Attribute packed
__attribute__((packed))
oder die Option -fpack-struct

siehe gcc onlinedocs

für Kommunikationsprotokolle sehr wichtig!

von Mathias G. (mgiaco)


Lesenswert?

Hallo,

Vielen Dank euch allen.
Also nein ist für einen Datenübertragung und da müssen die Bits leider 
so kompakt aneinander liegen - ich habe das Protokoll nicht gemacht.

"packed" habe ich natürlich auch probiert - bringt nicht wirklich was.

Ich werde es klassisch machen mit maskieren und schieben.

Danke

von A. S. (Gast)


Lesenswert?

Mathias G. schrieb:
> "packed" habe ich natürlich auch probiert - bringt nicht wirklich was.
Auch mit packed darf C nicht über die Bitgrenzen des Typs hinweg.

Die höchste Packungsdichte hättest Du daher mit 4-Byte-typen, da passen 
6- 5-Biter in 32 Bit.

von Bernd K. (prof7bit)


Lesenswert?

Volle schrieb:
> __attribute__((packed))
> [...]
> für Kommunikationsprotokolle sehr wichtig!

Es ist eher wichtig daß man die Protokolle so designed daß alle Felder 
self-aligned sind und sich ohne krumme Offsets zu ergeben lückenlos 
zusammenfügen lassen, oder mit anderen Worten: es ist sehr wichtig daß 
man es so entwirft daß das packed überhaupt keinen Unterschied machen 
würde. Wenn Du irgendwo packed brauchst hast Du einen Designfehler.

von Mathias G. (mgiaco)


Lesenswert?

:-) Ich werde es meine Chef sagen :-)
Ne aber stimmt vollkommen das Problem ist halt wenn man überall Bits und 
Bytes sparen will/muss

von Yalu X. (yalu) (Moderator)


Lesenswert?

Mathias G. schrieb:
> "packed" habe ich natürlich auch probiert - bringt nicht wirklich was.

Ich habe es auch mal ausprobiert: Mit arm-none-eabi-gcc 6.2.0 und
__attribute__((packed)) und ohne das gcc_struct-Attribut (das auf dem
ARM sowieso keine Bedutung hat) ist die Struktur 7 Byte groß, d.h. es
verbleiben keine ungenutzten Bits.

von Peter II (Gast)


Lesenswert?

Bernd K. schrieb:
> Es ist eher wichtig daß man die Protokolle so designed daß alle Felder
> self-aligned sind und sich ohne krumme Offsets zu ergeben lückenlos
> zusammenfügen lassen, oder mit anderen Worten: es ist sehr wichtig daß
> man es so entwirft daß das packed überhaupt keinen Unterschied machen
> würde. Wenn Du irgendwo packed brauchst hast Du einen Designfehler.

wie willst du das machen, eventuell muss man bei einer Plattform auf 
256bit alignen?

Beim lesen werden die Daten einfach mit Bitoperationen in eine passenden 
Struktur kopiert und beim senden in den Sendepuffer. Ich halte es für 
sinnlos das ein Programm die genaue Struktur von Daten der Übertragung 
abbilden soll.

von Bernd K. (prof7bit)


Lesenswert?

Peter II schrieb:
> wie willst du das machen,

Einfach jedes Element an seiner eigenen Größe ausrichten. Bytes an 1ern, 
Zweibytige and 2ern, Vierbytige an 4ern, Achtbytige an 8ern, etc. So 
mögen das alle aktuell gängigen CPUs und auch die der letzten 30 Jahre 
am liebsten.

> eventuell muss man bei einer Plattform auf
> 256bit alignen?

Die will ich sehen. Und ich glaub nicht das zukünftige CPUs in 
irgendeiner Hinsicht wieder schlechter werden sollen als heutige.

Ganz egal ob Du es mit nem Struct machst oder sie einzeln aus dem Buffer 
herauskratzt, wenn die Daten bereits ordentlich aligned im 
Empfangspuffer liegen hat der Compiler ne realistische Chance die 
Zugriffe schön zu optimieren ohne umständliche Schiebereien und 
Verrenkungen anzustellen.

von Peter II (Gast)


Lesenswert?

Bernd K. schrieb:
> Ganz egal ob Du es mit nem Struct machst oder sie einzeln aus dem Buffer
> herauskratzt, wenn die Daten bereits ordentlich aligned im
> Empfangspuffer liegen hat der Compiler ne realistische Chance die
> Zugriffe schön zu optimieren ohne umständliche Schiebereien und
> Verrenkungen anzustellen.

es ist aber oft so, das man nicht alle Anforderungen zusammen umsetzen 
kann.

Bei Ipv4 ist es auch nicht schön aligned. Bei IPv6 haben sie es wieder 
besser gemacht, aber dort gibt es dann wieder optionale felder die den 
Rest veschieben können.

Bei der Übertragung ist es wichtiger Platzsparend zu übertragen, als auf 
ein alignmend zu achten.

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.