C - Bit eines Bytes beschreiben

OP #2520727
Lesenswert?

Hallo,

x |= (Datenwert << 5) <-- Dass würde das 5te bit von x mit dem Wert 
"Datenwert beschreiben.

Könnt Ihr mir sagen, wie es einfacher geht.

Ich will nur ein bit in einem Byte, bzw in einem Integer beschreiben.

Aber soetwas wie

int Testvariable;


Testvariable.0 = 1;
Testvariable.1 = 0;
Testvariable.2 = 0;

Geht nicht. Könnt Ihr mir sagen wie ich es Syntax echt machen müsste ?



LG Tim
#2520736
Lesenswert?

Tim E. schrieb:
> Hallo,
>
> x |= (Datenwert << 5) <-- Dass würde das 5te bit von x mit dem Wert
> "Datenwert beschreiben.


Nicht wirklich.
Damit kannst du 1 Bit auf 1 setzen aber nicht auf 0. 'beschreiben' ist 
daher irgendwie das falsche Wort.


  x |= ( 1 << Bitnummer );   // Bit auf 1 setzen
  x &= ~( 1 << Bitnummer );  // Bit auf 0 setzen

> Könnt Ihr mir sagen, wie es einfacher geht.

Was gefällt dir daran nicht?
Persönliche Seite #2520743
Lesenswert?

Tim E. schrieb:
> Dass würde das 5te bit von x mit dem Wert
> "Datenwert beschreiben.

Nein, da_s_ würde es nicht, beziehungsweise nur dann, wenn Datenwert 1 
ist.


Ein Bit setzen (mit dem Wert 1 beschreiben) geschieht so, wie von Dir 
beschrieben:

  Wert |= (1 << Bitnummer);

ein Bit löschen (mit dem Wert 0 beschreiben) aber geschieht so:

  Wert &= ~(1 << Bitnummer);


So und nur so wird das in C gemacht. "Einfacher" geht es nicht, aber 
"Einfacher" würde es auch durch die von Dir gewünschte Notation nicht 
werden.

Es gibt Krücken, beispielsweise die Kombination eines Bitfelds und eines 
Bytes in einer union, aber das bewirkt letztlich auch nichts anderes 
und hilft nur Leuten, das Erlernen herauszuzögern, wie man es richtig 
anstellt.
#2520765
Lesenswert?

Bitnummern kann man sich auch definieren. Ungefähr so...
1
#define BITF (1<<15)
2
...
3
...
4
#define BIT8 (1<<8)
5
#define BIT7 (1<<7)
6
#define BIT6 (1<<6)
7
...
8
...
9
#define BIT0 (1<<0)
...sieht das dann beim MSP430 aus, weil der ja eine 16Bit-Maschine ist.

Beispiel für Bit 3 und 4...
setzen:
1
foo |= BIT3 + BIT4;
löschen:
1
foo &= ~(BIT3 + BIT4);

mfg mf
#2520778
Lesenswert?

Tim E. schrieb:
> Das es so lange und umständlich ist, wenn ich nicht weis ob es eine 0
> oder 1 ist, weil das unterschiedlich ist. Dann müsste ich immer ein If
> abfrage machen.

In der Zeit in der du da rumprüfst, ob jetzt was getan werden muss, ist 
es besser, es wird gleich getan. Du gibst den Sollwert eines Bits an. 
Den nimmt es ein, egal was vorher war.

Wenn man alternierendes Verhalten haben will wie ein einrastender 
Druckknopf, dann gibt es noch toggeln:
1
int main(void)
2
{
3
   uint8_t foo = BIT1;
4
   
5
   while(1)
6
      foo ^= BIT1 + BIT6;
Bit1 und Bit6 spielen jetzt Polizeiauto mit Blaulicht...

mfg mf

PS: Beim Löschen schön drauf schaun, dass die "~" da ist.
#2520792
Lesenswert?

Mini Float schrieb:
> In der Zeit in der du da rumprüfst, ob jetzt was getan werden muss, ist
> es besser, es wird gleich getan. Du gibst den Sollwert eines Bits an.
> Den nimmt es ein, egal was vorher war.
Da sei dir man nicht so sicher. Das sieht in C geschrieben zwar kurz und 
knapp aus, aber guck' dir mal an, was der Compiler daraus macht.

Denn das prüfen auf "0" ist ein einziger Befehl, der in einem Takt 
ausgeführt wird. jz, breq oder wie auch immer.

mfg.
#2520837
Lesenswert?

eori, andi oder ori sind Einzeiler im Assemblercode. Die konstanten 
Werte hinter dem "=" werden als solche erkannt und in die Anweisung 
codiert.

Gerade bei ifs in C, wenn sie einen Vergleichsoperator haben, werfen 
manche compiler immer noch ein tst als expliziten Nullvergleich ein, 
obwohl es meist nicht sein muss.

mfg mf
#2520867
Lesenswert?

Na, wenn du meinst.

if (Datenwert) Testvariable |= (1 << 5); else Testvariable &= ~(1 << 5);
  9c:  80 91 6c 00   lds  r24, 0x006C
  a0:  88 23         and  r24, r24
  a2:  21 f0         breq  .+8        ; 0xac <main+0x10>
  a4:  80 91 6b 00   lds  r24, 0x006B
  a8:  80 62         ori  r24, 0x20  ; 32
  aa:  03 c0         rjmp  .+6        ; 0xb2 <main+0x16>
  ac:  80 91 6b 00   lds  r24, 0x006B
  b0:  8f 7d         andi  r24, 0xDF  ; 223
  b2:  80 93 6b 00   sts  0x006B, r24

Testvariable &= ~(1 << 5);
  b6:  80 91 6b 00   lds  r24, 0x006B
  ba:  8f 7d         andi  r24, 0xDF  ; 223
  bc:  80 93 6b 00   sts  0x006B, r24
Testvariable |= (Datenwert << 5);
  c0:  90 91 6b 00   lds  r25, 0x006B
  c4:  80 91 6c 00   lds  r24, 0x006C
  c8:  82 95         swap  r24
  ca:  88 0f         add  r24, r24
  cc:  80 7e         andi  r24, 0xE0  ; 224
  ce:  89 2b         or  r24, r25
  d0:  80 93 6b 00   sts  0x006B, r24

mfg.
Gast #2520873
Lesenswert?

Hi

>eori, andi oder ori sind Einzeiler im Assemblercode.

eori gibt es nicht. Zumindest bei den Registern haben die GCC-Erfinder 
die Möglichkeiten des T-Flags völlig ignoriert.

  set
  bld Rxy,n

setzt Bit n (0...7) im Register xy

  clt
  bld Rxy,n

löscht Bit n (0...7) im Register xy

MfG Spess
#2520887
Lesenswert?

Thomas Eckmann schrieb:
> Na, wenn du meinst.

Jetzt bist du aber unfair :-)

>
> if (Datenwert) Testvariable |= (1 << 5); else Testvariable &= ~(1 << 5);
>   9c:  80 91 6c 00   lds  r24, 0x006C
>   a0:  88 23         and  r24, r24
>   a2:  21 f0         breq  .+8        ; 0xac <main+0x10>
>   a4:  80 91 6b 00   lds  r24, 0x006B

hier
>   a8:  80 62         ori  r24, 0x20  ; 32
passiert das Bit setzen

>   aa:  03 c0         rjmp  .+6        ; 0xb2 <main+0x16>
>   ac:  80 91 6b 00   lds  r24, 0x006B

hier
>   b0:  8f 7d         andi  r24, 0xDF  ; 223
das Bit löschen

>   b2:  80 93 6b 00   sts  0x006B, r24

Das der Compiler den Inhalt der Variablen laden und Speichern muss, ist 
klar. Wenn du anstelle von Variablen Port-Register genommen hättest, 
wäre das nicht notwendig gewesen (insofern warst du unfair).
#2520910
Lesenswert?

Karl Heinz Buchegger schrieb:
> Jetzt bist du aber unfair :-)
Wieso?
Es ging darum, ob eine If-Abfrage und dann entweder Löschen oder Setzen 
schneller ist, oder ob es günstiger ist, grundsätzlich zu löschen und 
dann zu setzen unabhängig vom Inhalt der Variable.

> Wenn du anstelle von Variablen Port-Register genommen hättest,
> wäre das nicht notwendig gewesen (insofern warst du unfair).
Das wollte ich auch erst, weil ich keine Lust hatte, noch zwei Variable 
hinzuschreiben. Aber dann habe ich gesehen, daß es oben um Variable 
ging.

mfg.
#2520930
Lesenswert?

Thomas Eckmann schrieb:
> Karl Heinz Buchegger schrieb:
>> Jetzt bist du aber unfair :-)
> Wieso?
> Es ging darum, ob eine If-Abfrage und dann entweder Löschen oder Setzen
> schneller ist, oder ob es günstiger ist, grundsätzlich zu löschen und
> dann zu setzen unabhängig vom Inhalt der Variable.

OK.
Dann hab ich nicht mitgekriegt, warauf du hinaus wolltest. Und ich denke 
Mini-Float wollte seinen ursprünglichen Kommentar auch anders verstanden 
wissen.
#2520931
Lesenswert?

Karl Heinz Buchegger schrieb:
> Wenn du anstelle von Variablen Port-Register genommen hättest
Jetzt mal die Registervariante:

if (GPIOR1) GPIOR0 |= (1 << 5); else GPIOR0 &= ~(1 << 5);
  9c:  82 b3         in  r24, 0x12  ; 18
  9e:  88 23         and  r24, r24
  a0:  11 f0         breq  .+4        ; 0xa6 <main+0xa>
  a2:  8d 9a         sbi  0x11, 5  ; 17
  a4:  01 c0         rjmp  .+2        ; 0xa8 <main+0xc>
  a6:  8d 98         cbi  0x11, 5  ; 17

GPIOR0 &= ~(1 << 5);
  a8:  8d 98         cbi  0x11, 5  ; 17
GPIOR0 |= (GPIOR1 << 5);
  aa:  91 b3         in  r25, 0x11  ; 17
  ac:  82 b3         in  r24, 0x12  ; 18
  ae:  82 95         swap  r24
  b0:  88 0f         add  r24, r24
  b2:  80 7e         andi  r24, 0xE0  ; 224
  b4:  89 2b         or  r24, r25
  b6:  81 bb         out  0x11, r24  ; 17

mfg.
#2520939
Lesenswert?

Ersetz doch mal das GPIOR1 durch eine Konstante.

Denn das wollte der TO ja wirklich machen und hat sich nur ungeschickt 
ausgedrückt


Zitat

> Also sowas wie
> int Testvariable;
>
>
> Testvariable.0 = 1;
> Testvariable.1 = 0;
> Testvariable.2 = 0;

Er weiß zur Compiletime, welches Bit er 0 oder 1 setzen will.
#2520944
Lesenswert?

Karl Heinz Buchegger schrieb:
> Er weiß zur Compiletime, welches Bit er 0 oder 1 setzen will.
Das ist klar. Das sind dann im GPIO 2 Befehle.

Aber ich bin jetzt davon ausgegangen:
>x |= (Datenwert << 5) <-- Dass würde das 5te bit von x mit dem Wert
>"Datenwert beschreiben.
Naja, da hat er sich wohl wirklich unglücklich ausgedrückt. Oder ich 
hab' das unglücklich verstanden.

mfg.

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