www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik union mit bitfeld in struct in c


Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich möchte in einer struktur:

typedef struct
{
     uint8_t * feld1[10];
     uint8_t * feld2[10];
     ...
     uint8_t * feld8[10];
     uint8_t feld1_ok   :1,
             feld2_ok   :1,
             ...
             feld3_ok   :1;
}felder;

gern eine weitere Variable vom typ 8 bit unterbringen die 
adresstechnisch genau an der stelle liegt wo auch die 8 einzelnen 
ok-Bits liegen.

typedef struct
{
     uint8_t * feld1[10];
     uint8_t * feld2[10];
     ...
     uint8_t * feld8[10];
     union
     {
         uint8_t feld1_ok   :1,
                 feld2_ok   :1,
                 ...
                 feld8_ok   :1;
         uint8_t alle;
     };
}felder;

wird nicht angemekkert aber funktioniert trotzdem nicht, habe ich das 
mit der union falsch verstanden, muss ich zuvor einen typen machen, oder 
kann ich das auch so in einem lösen?

Wenn ich dies geraffel einer Funktion übergebe, also darauf zeige:

felder datensatz;
felder * p_datensatz;

p_datensatz=&datensatz;

dann sollte ich doch so

*p_datensatz->feld1[0]='A';
p_datensatz->feld1_ok=1;

zugreifen können. Was habe ich vergessen?

Gruß,
H.

Autor: Antwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Union wird schon falsch deklariert. Du hast ihm keinen Namen 
gegeben. Ein Union verhält sich im ersten Moment wie ein struct, nur das 
es nur eine der möglichen Variablen speichern kann. Du müsstest es also 
wie folgt verändern:
typedef struct
{
     uint8_t * feld1[10];
     uint8_t * feld2[10];
     ...
     uint8_t * feld8[10];
     union my union
     {
         uint8_t feld1_ok   :1,
                 feld2_ok   :1,
                 ...
                 feld8_ok   :1;
     };
}felder;

Ansprechen dann wie folgt:
p_datensatz->my_union_feld1_ok = 1;

Autor: Antwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hatte einen Tippfehler
p_datensatz->my_union.feld1_ok = 1;


Aber ich denke mal nicht das es sich so verhalten wird wie du denkst. 
Schließlich hast du nicht alle ok felder im union zur Verfügung.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hey,

bin gerad hier:

http://cboard.cprogramming.com/c-programming/10297...

1)das mit deinem Underline im Zugriff ist unverständlich!?
2)der Name beim Struct steht aber nach der geschweiften klammer bei der 
union nicht?


Gruß,
H.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>verhalten wird wie du denkst<<

warum, 8 ok, uint8_t alle?

H

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes schrieb:

> wird nicht angemekkert aber funktioniert trotzdem nicht, habe ich das
> mit der union falsch verstanden, muss ich zuvor einen typen machen, oder
> kann ich das auch so in einem lösen?

du musst zunächst die 8 Bit mittels einer Struktur zusammenfassen, ehe 
du dann mittels union, zu der Struktur dann einen uint8_t parallel legen 
kannst.

In einer union werden ALLE Elemente, egal wieviele, übereinander gelegt.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es sei darauf hingewiesen, dass die einschlägigen C-Standards bezüglich 
Bitfeldern festlegen, dass nichts festgelegt ist :-)

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmm...

teste gerad ein wenig rum...

warum muss ich die bitfeld bits denn noch mit einem struct 
zusammenfassen bevor ich sie über das Byte legen kann, sie sind doch 
schon in einem byte?

H.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt keine Sonderbehandlung von Bits in unions. Sie sind alternativ 
zu jedem anderen Eintrag innerhalb der union; also auch zu anderen 
Bits. Deswegen musst Du sie zusammenfassen, wenn sie insgesamt 
alternativ zu anderen Elementen der union sein sollen.

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe das mal alles nachgepflegt:


typedef struct
{
     uint8_t * feld1[10];
     uint8_t * feld2[10];
     ...
     uint8_t * feld8[10];
     union
     {
         struct
         {
             uint8_t feld1   :1,
                     feld2   :1,
                     ...
                     feld8   :1;
         }bit;
         uint8_t alle;
     }ok;
}felder;

Zugriff mache ich so:

felder datensatz;
felder * p_datensatz;

p_datensatz=&datensatz;

*p_datensatz->feld1[0]='A';
p_datensatz->ok.bit.feld1=1;
p_datensatz->ok.alle=0xFF;

Das scheint zu funktionieren, ich mache das gerade im MS Studio, dort 
erscheinen die Bits dann als 32 bit variablen dargestellt deren bits 
dann alle auf 1 gehen. Da man in dem Fall die Adresse nicht sehen kann 
bin ich nicht 100%ig sicher, das die bits und die "gesamt" variable auch 
wirklich übereinander liegen und das Bitfeld auch greift.

Habe ich es denn richtig umgesetzt?
gibt es eine Möglichkeit das .bit. aus der Zugriffstruktur heraus zu 
bekommen? Ich würde die Ebene gern sparen.

Gruß und vielen Dank bis hierher,
H.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hannes schrieb:
> gibt es eine Möglichkeit das .bit. aus der Zugriffstruktur heraus zu
> bekommen? Ich würde die Ebene gern sparen.

Der gcc erlaubt auch anonyme unions; wenn es nicht portabel sein
muß (was es ja faktisch gar nicht ist), geht es auch ohne.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Da man in dem Fall die Adresse nicht sehen kann
>bin ich nicht 100%ig sicher, das die bits und die "gesamt" variable auch
>wirklich übereinander liegen und das Bitfeld auch greift.

Nun, das ist ja genau die interpretation von "union". Alle Einträge 
liegen an der selben Adresse!
Aber Du kannst selbstverständlich auch die Adresse nachprüfen.

& p_datensatz->ok.bit

und

& p_datensatz->ok.alle

müssen das selbe ergeben.

>gibt es eine Möglichkeit das .bit. aus der Zugriffstruktur heraus zu
>bekommen? Ich würde die Ebene gern sparen.

Nein.

Ist das wirklich beabsichtig, das Du Vektoren von Zeigern anlegst?

     uint8_t * feld1[10];

Ich frage weil Du den nicht alloziierten Vektorelementen dann Zeichen 
zuweist. Oder fehlt die Alloziierung nur in Deinem Zitat?

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Ist das wirklich beabsichtig, das Du Vektoren von Zeigern anlegst?<<

nein, da habe ich mich versehen. Es sind strings, Felder von chars. Ist 
mir beim erstellen des Beispiels da rein gerutscht...


>>& p_datensatz->ok.bit<<

töffel, daran habe ich nicht gedacht. Hab das in der Zwischenzeit anders 
nachgewiesen, aber so ists natürlich noch einfacher, danke :-)

Dann habe ich alles was ich brauche, danke.
H.

Ps.: die Anspielung auf die -nicht kompatibilität- ist doch auf die MSB 
LSB Geschichte bei Bitfeldern bezogen, oder?
Dann stimmt die Aussage meiner Meinung nach nur dann wenn man der 
Bitcodierung der Variablen "alle" keine Wertung in Bezug auf die 
einzelnen Bits bei der Zuweisung eines Wertes beipflichtet. Sie wird nur 
zum resetten aller Bits benutzt.
Wenn man diese Struktur zudem nicht über eine Systemunabhängige 
Schnittstelle wie Ethernet oder ähnliches an ein anderes System mit 
selbiger Struktur im code übermittelt, erwarte ich damit keine Probleme.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ps.: die Anspielung auf die -nicht kompatibilität- ist doch auf die MSB
LSB Geschichte bei Bitfeldern bezogen, oder?

Das bezog sich auf die Sprachkompatibilität. In C sind anonyme 
Strukturen nicht möglich. In C++ allerdings schon. Da der GCC beides 
kann lässt er, falls Du nicht ausdrücklich z.B. C99 festgelegt hast auch 
anonyme Strukturen in C zu.

Was die Zuordnung von Bits des Bitfeldes zu Bits des alternativen uint8 
betrifft, so ist im Sprachstandard nichts zugesichert. Das ist soweit 
richtig, hat aber nichts damit zu tun ob anonyme Strukturen zulässig 
sind oder nicht. Deswegen sind solche Dinge nicht "transportabel" (das 
ist hier der korrekte Begriff im Ggs. zu kompatibel).

Dennoch ist das Verhalten eines Compilers auf einer Maschine in der 
Regel konsistent implementiert. D.h. das er die Bits immer in der selben 
Reihenfolge anordnet.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry. "Transportabel" ist eigentlich auch nicht ganz üblich. "Portabel" 
ist hier besser. Ist beides das selbe, aber was anderes als 
"Kompatibel".

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Huch schrieb:
> Was die Zuordnung von Bits des Bitfeldes zu Bits des alternativen uint8
> betrifft, so ist im Sprachstandard nichts zugesichert.

Und für unions ist dort festgelegt, daß man auf gar keinen Fall ein 
anderes Element lesen darf als das, das man zuletzt geschrieben hat.

Autor: Marco U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sofern ich mich erinnern kann werden, selbst wenn man nur 1 Bit 
verwendet, dennoch als kleinste Einheit sizeof(int) reserviert. Die 
restlichen Bit des Byte "liegen brach". Was die Verwendung von 
Bitfeldern mit geringer Größe meiner Meinung nach obsolet macht.

Aus C von A bis Z von Jürgen Wolf

struct robo {
   unsigned int sensor1:1;
   unsigned int sensor2:1;
   unsigned int sensor3:1;
   unsigned int schalter:1;
   unsigned int Ausgabe:4;
} Roboter1;

Jetzt benötigt die Struktur im Grunde nur noch acht Bits (ein Byte). 
Wenn Sie allerdings mit sizeof prüfen, werden Sie feststellen, dass 
dieses Bitfeld trotzdem vier Byte belegt. Dies liegt daran, dass das 
kleinstmögliche Rechnerwort, das der Compiler für ein Bitfeld 
reserviert, sizeof(int) groß ist. Die restlichen drei Bytes in diesem 
Beispiel sind praktisch leer. Gleiches gilt hierbei natürlich auch, wenn 
Sie beispielsweise ein Bitfeld mit 40 Bits (fünf Bytes) erstellen. Hier 
muss der Compiler ein weiteres Rechnerwort (sizeof(int)) reservieren, 
sodass das fünfte Byte am Anfang des nächsten Rechnerworts liegt und 
somit insgesamt 8 Bytes benötigt werden.

Quelle: 
http://openbook.galileocomputing.de/c_von_a_bis_z/...

Gruß
Marco

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marco Ullrich schrieb:
> Sofern ich mich erinnern kann werden, selbst wenn man nur 1 Bit
> verwendet, dennoch als kleinste Einheit sizeof(int) reserviert.

Ja, wenn du als Typ für die Elemente int angibst. Abhängig vom Compiler 
sind aber durchaus auch kleinere Typen erlaubt (ein Compiler muß 
mindestens mit bool, int und unsigned int umgehen können, darf aber auch 
beliebige andere Integertypen unterstützen). Folgendes Programm gibt bei 
mir
1
 aus:
#include <stdio.h>

struct bitfield
{
    unsigned char a : 1;
    unsigned char b : 2;
    unsigned char c : 3;
};

int main()
{
    printf("%d\n", sizeof(struct bitfield));
}

Da sowieso so ziemlich alle Eigenschaften von Bitfeldern höchst 
compilerspezifisch sind, macht es auch nichts mehr aus, wenn man sich 
auch darauf verläßt, daß das so geht.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.