Forum: Compiler & IDEs 2bit array[ ] ?


von tronic (Gast)


Lesenswert?

Hallo mal wieder,

eine 8bit Variable definiert man ja so:

uint8_t variable;

ich hab nun 30 Module die entweder den Zustand "0" oder "1" haben,
diese Zustände möchte ich möglichst in einem array speichern.

uint8_t array[30];

so ein array verbraucht viel platz, ist auch nur ein 2bit array
möglich?
wie sieht der code hierfür aus?

thx
tronic

von tronic (Gast)


Lesenswert?

äh natürlich ein 1-bit array nicht 2

von Ludwig Meyerhoff (Gast)


Lesenswert?

Hallo!

Ich habe gestern einen Blick in das avr-gcc Tutorial geworfen, und von
"Bitfeldern" gehört:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Bitfelder

Laut Beschreibung (bin zum ersten Mal auf das Konstrukt gestossen)
sollte das genau das sein, was Du suchst?



SalutI!

Ludwig

von Peter (Gast)


Lesenswert?

Wie wär's mit einem 32 Bit Integer? Da haben 32 x (0 oder 1) Platz in
bloss vier Bytes! ;o))

#define MyBit0 = 0x00000001UL
#define MyBit1 = 0x00000002UL
#define MyBit2 = 0x00000004UL
#define MyBit3 = 0x00000008UL
#define MyBit4 = 0x00000010UL
#define MyBit5 = 0x00000020UL
//etc...

uint_32t MyFlags;

Falls Du ein 8 Bit-uC verwendest(z.B. den AVR), dann wird es natürlich
effizienter, wenn Du stattdessen 4 x uint_8t statt 1 x uint32t
benutzt:

uint_8t MyFlagsA,MyFlagsB,MyFlagsC,MyFlagsD;
// oder auch als Array
uint_8t MyFlags[4]   // => MyFlags[0..3]

Du musst Dir dann halt merken, welches Flag-Bit in welchem Byte steht!

C bietet sogar die Möglichkeit, Strukturen Bit-Weise zu definieren,
hab's aber noch nie verwendet, da es ohne genau so gut geht!

Gruss Peter

von Rolf Magnus (Gast)


Lesenswert?

> C bietet sogar die Möglichkeit, Strukturen Bit-Weise zu
> definieren, hab's aber noch nie verwendet, da es ohne genau so gut
> geht!

Das sind die Bitfelder, von denen Ludwig schreibt. Sie eignen sich
hervorragend dafür. Man muß allerdings beachten (egal welche Methode
man verwendet), daß durch die Bitschubsereien der Code ein Stück größer
wird. Man erkauft sich also die RAM-Ersparnis mit mehr Codegröße. Aber
man hat ja meistens mehr Code- als Datenspeicher überig.
Ach ja, bei manchen Controllern, wie z.B. dem Atmega88 gibt's auch
noch (ich glaub' drei) I/O-Register, die vom Benutzer beliebig
verwendet werden können. Da der Prozessor spezielle Instruktionen zum
Ändern und zum Abfragen eines I/O-Regiter-Bits hat, gibt's hier den
Overhead nicht. Auf anderen Controllern dürften sich bei akutem
Platzmangel auch unbenutzte I/O-Register zweckentfremden lassen, Z.B.
ein OCR-Register, wenn man die entsprechende Compare-Unit nicht
benutzt.

von Simon K. (simon) Benutzerseite


Lesenswert?

Für zwei Zustände braucht man übrigens nur 1 bit...

PS: Kleine Frage zu den Bitfeldern. Dazu nehme ich mal das Beispiel aus
dem Tutorial:
1
struct {
2
   unsigned char bStatus_1:1; // 1 Bit für bStatus_1
3
   unsigned char bStatus_2:1; // 1 Bit für bStatus_2
4
   unsigned char bNochNBit:1; // Und hier noch mal ein Bit
5
   unsigned char b2Bits:2;    // Dieses Feld ist 2 Bits breit
6
   // All das hat in einer einzigen Byte-Variable Platz.
7
   // die 3 verbleibenden Bits bleiben ungenutzt
8
} x;

Warum muss denn jetzt vor jedes Bit/Bitpaar noch "unsigned char
stehen" ?

Wenn ich
1
struct {
2
   unsigned char bStatus_1:1; // 1 Bit für bStatus_1
3
} x;

definiere, ist dann sizeof(x) == 1 ? Sprich 8 Bit groß, nur 7 Bits
werden nicht benutzt?

Würde das heißen, dass sizeof(x) bei folgendem Fall 2 sein wird?
(Sprich 2 Bytes werden reserviert, 7 Bits ungenutzt)

[C]
struct {
   unsigned char bStatus_1:8;
   unsigned char bStatus_2:1;
} x;


Danke schonmal!

von Simon K. (simon) Benutzerseite


Lesenswert?

+ [/C]


Achja: Bitfeldoperationen sollten (beim AVR zumindest) doch nicht
langsamer oder größer als "normale" Variablenoperationen.

Dabei denke ich an Anweisungen wie sbr, cbr etc...

von tronic (Gast)


Lesenswert?

das problem ist das ich die Zustände nur durch eine Zählschleife einfach
übergeben möchte,
also von 1-30 zählen, und den abgefragten Zustand (1 oder 0) zuweisen.
wenn ich  4 variablen à 8bit habe geht das komplizierter, als wenn man
einfach ein 1Bit array[]
durchnummeriert...
gibts hierfür was?
thx.

von Karl H. (kbuchegg)


Lesenswert?

@tronic

Dafür gibts nichts in C. Es gibt kein 1-Bit-Array.

@Simon
> Warum muss denn jetzt vor jedes Bit/Bitpaar noch "unsigned char
> stehen" ?

Bei einem einzelnen Bit macht das zugegebenermassen nicht
wirklich Sinn. Aber ein 2-Bit Bitfeld (oder größer) könnte
theoretisch auch 'signed' sein. Kommt zwar selten vor,
ist aber möglich. Und es muss auch nicht char sein. Wenn
du 16 Bits brauchst (und ein int 16 Bits gross ist, dann
spricht nichts dagegen die Bits in einen signed/unsigned
int hineinzupfriemeln.

> definiere, ist dann sizeof(x) == 1 ? Sprich 8 Bit groß, nur 7 Bits
> werden nicht benutzt?

Ja. Kleiner als sizeof(x) == 1 geht nicht. (*)

> Würde das heißen, dass sizeof(x) bei folgendem Fall 2 sein wird?
> (Sprich 2 Bytes werden reserviert, 7 Bits ungenutzt)

Ganz genau.
sizeof ist immer eine ganze Zahl. (*)

> doch nicht langsamer oder größer als "normale"
Variablenoperationen.

Doch, natürlich. Dein µC arbeitet ja genauso Byte-orientiert.
Wenn du nur ein Bit setzen willst, muss trotzdem das komplette
Byte aus dem Speicher geholt werden. Dann wird das Bit gesetzt
und das Byte zurückgeschrieben. Dem gegenüber steht eine Zuweisung
an einen normalen unsigned char, bei dem der vorhergehende Zustand
des kompletten Bytes völlig uninteressant ist.
Im Grunde kann der Compiler auch nicht zaubern. Um ein Bit zu setzen
kommt er nicht an
   x = x | Maske;
vorbei. Nur sparst du dir halt mit Bitfeldern den Schreibaufwand.
Den übernimmt dann der Compiler für dich.


(*) Das hat beides damit zu tun, dass man ja mit diesem struct
wieder Arrays aufbauen können muss.

von Simon K. (simon) Benutzerseite


Lesenswert?

@Karl Heinz: Danke für die Erläuterung. Damit wäre für mich alles
geklärt ;)

von Rolf Magnus (Gast)


Lesenswert?

> Achja: Bitfeldoperationen sollten (beim AVR zumindest) doch nicht
> langsamer oder größer als "normale" Variablenoperationen.
>
> Dabei denke ich an Anweisungen wie sbr, cbr etc...

sbr ist nur ein anderer Name für ori, cbr für andi. Deshalb hat der AVR
hier keinerlei Vorteil durch diese Befehle. Und dann kommt der von Karl
Heinz erwähnte Speicherzugriff dazu. Nur bei I/O-Registern hat der AVR
mit sbi und cbi die Möglichkeit, direkt einzelne Bits zu ändern und mit
sbic und sbis basierend auf ihnen zu verzweigen.

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.