Forum: Mikrocontroller und Digitale Elektronik INT nur 6 Bit kopieren; Rest belassen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Stefan M. (stefatronik)


Bewertung
1 lesenswert
nicht lesenswert
Hallo,

ich möchte gerne in eine 8-Bit INT eine andere INT kopieren, von dieser 
jedoch nur die niedrigen 6 Bit. Die höherwertigen 2 Bit der 
ursprünglichen INT sollen bleiben.

Mit
1
a = (b & 63);

würde ich zwar in b an den betr. Stellen Nullen erzeugen, aber meine 
höherwertigen Bit, die ich erhalten möchte, werden gelöscht.

Wie würdet ihr das lösen?

von Chris D. (myfairtux) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Bspw. so:

Du musst nur die "alten" oberen Bits von a wieder anhängen:

a = (b & 0x3F) | (a & 0xC0);

Edit: Besser mit oder ... oh, Marc war schneller :-)

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Bewertung
-1 lesenswert
nicht lesenswert
Stefan M. schrieb:
> Wie würdet ihr das lösen?

 a = (a & 0xC0) | (b & 0x3F);

von Nico W. (nico_w)


Bewertung
1 lesenswert
nicht lesenswert
Zunächst solltest du dir die hexadezimale Schreibweise angewöhnen. Im 
ersten Moment vielleicht kurz gewöhnungsbedürftig, aber später 
erleichtert das einem das Lesen ungemein.

Also
1
a = (b & 0x3F);

Was willst du aber genau? Steht in a schon was drinne, was du behalten 
möchtest?
1
a = (a & 0xC0); // behalte die ersten beiden Bits
2
a = a | (b & 0x3F); // verOder die letzten 6 Bits
3
4
bzw. in kurz
5
6
a &= 0xC0;
7
a |= (b & 0x3F);

von Flupsi (Gast)


Bewertung
1 lesenswert
nicht lesenswert
so?

a = (b & 63) | (a & C0);

von Flupsi (Gast)


Bewertung
1 lesenswert
nicht lesenswert
korrektur: a = (b & 0x3F) | (a & 0xC0);

Ah hatte Marc schon so vorgeschlagen...

Beitrag #4935224 wurde vom Autor gelöscht.
von Marc V. (Firma: Vescomp) (logarithmus)


Bewertung
-1 lesenswert
nicht lesenswert
Chris D. schrieb:
> Edit: Besser mit oder ... oh, Marc war schneller :-)

 Nein, du warst schneller ;-)

 Und es kommt auf das selbe hinaus - sowohl "add" als auch "or"
 brauchen jeweils 1 Takt - und Überlauf kann es sowieso nicht geben.

von Stefan M. (stefatronik)


Bewertung
1 lesenswert
nicht lesenswert
Ja super dank euch.

von Chris D. (myfairtux) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Marc V. schrieb:
>  Und es kommt auf das selbe hinaus - sowohl "add" als auch "or"
>  brauchen jeweils 1 Takt - und Überlauf kann es sowieso nicht geben.

Ja, der Compiler (sofern Stefan einen verwendet) wird daraus dasselbe 
machen - aber mit "or" entspricht es eher der "reinen Lehre" (nur 
boolsche Operationen) :-)

von Alex (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Hi Nico,
Nico W. schrieb:
> Zunächst solltest du dir die hexadezimale Schreibweise angewöhnen.
> Im
> ersten Moment vielleicht kurz gewöhnungsbedürftig, aber später
> erleichtert das einem das Lesen ungemein.
magst du das bitte ein wenig näher Erläutern, inwiefern die das Lesen 
erleichtert?

Ich selbst bin kein richtiger Programmierer, und tue mich entsprechend 
jedes Mal schwer damit, hexadezimale Schreibweise im Code zu lesen.

Vielen Dank,
Alex

von Nico W. (nico_w)


Bewertung
1 lesenswert
nicht lesenswert
Hexadezimal ist daher besser zu lesen, weil man zumeist sehr schnell 
sieht wie viele 1en man hat. Hexadezimal ist einfach deutlich näher an 
der binären Darstellung.

0xf = 0b1111 = 15
0xff = 0b11111111 = 255

Wie du schon schön da erkennen kannst, kann man für 4 1en einfach nen F 
anhängen. Bei Dezimal muss man rechnen.

0xC = 0b1100 = 12
0xC0 = 0b11000000 = 192

Einfach damit ein wenig beschäftigen. Ich habe vor ein paar Jahren auch 
nicht verstanden warum das so viel besser ist, bzw. warum das jeder so 
nutzt. Irgendwann ist dann der Groschen gefallen.

: Bearbeitet durch User
von Chris D. (myfairtux) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Alex schrieb:
> Hi Nico,
> Nico W. schrieb:
>> Zunächst solltest du dir die hexadezimale Schreibweise angewöhnen.
>> Im
>> ersten Moment vielleicht kurz gewöhnungsbedürftig, aber später
>> erleichtert das einem das Lesen ungemein.
> magst du das bitte ein wenig näher Erläutern, inwiefern die das Lesen
> erleichtert?
>
> Ich selbst bin kein richtiger Programmierer, und tue mich entsprechend
> jedes Mal schwer damit, hexadezimale Schreibweise im Code zu lesen.

Bei der dezimalen Schreibweise ist es sehr schwer, zu erkennen, welche 
Bits denn jetzt wirklich gesetzt bzw. gelöscht werden.

Bei der hexadezimalen (korrekt heisst es eigentlich "sedezimal", das 
Attribut verwendet aber niemand ;-) Schreibweise hast Du immer genau 
vier Bits in einer Ziffer gruppiert. Du musst Dir also nur die 16 
verschiedenen "Ziffern" in ihrer Bitdarstellung merken und kannst an 
einer Hexadezimalzahl sofort erkennen, welche Bits gesetzt sind.

Beispiel: 0x1000 heisst: die unteren 3*4 Bits sind null, nur das Bit 12 
ist gesetzt, ausgeschrieben als Dualzahl wäre das 0001 0000 0000 0000.

Der dezimalen Schreibweise 4096 sieht man das nicht an.

: Bearbeitet durch Moderator
von Stefan M. (stefatronik)


Bewertung
1 lesenswert
nicht lesenswert
Ich finde die Argumente für HEX sind plausibel, allerdings ist die 
anschaulichste Darstellung dann wohl eher Binär, oder? Jedenfalls, so 
lange wir mit 8-Bit Zahlen arbeiten und nicht mit 16 Bit...

von Chris D. (myfairtux) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Ja, je nach C-Compiler gibt es die auch. Der GCC-AVR kann das, wenn man 
"0b" voranstellt:

255 = 0xFF = 0b11111111

Dein Beispiel wäre also so etwas:

(b & 0x3F) | (a & 0xC0) wird zu

(b & 0b00111111) | (a & 0b11000000)

Aber man sieht, dass mit der zunehmenden Anzahl an Bits das Ganze 
unleserlich wird. Bei 32 Bit lässt man das dann lieber ;-)

Ist das schon in irgendeinen C-Standard eingeflossen?
Genaueres dazu sollten aber die Compilerexperten hier wissen.

: Bearbeitet durch Moderator
von Nico W. (nico_w)


Bewertung
1 lesenswert
nicht lesenswert
Alle Zahlen die länger als 3 bis 5 Ziffern haben sind gehirnbedingt 
schlecht zu erfassen. 0b10000000 oder 0b1000000 kannst du schlecht 
unterscheiden. Daher würde ich auch bei 8bit immer Hex vorziehen.

von Alex (Gast)


Bewertung
1 lesenswert
nicht lesenswert
Vielen Dank für eure Rückmeldung. Ich finde/fand die binäre Darstellung 
immer am Anschaulichsten, da ich sofort sehen kann, welches Bit im 
Register gesetzt / gelöscht ist, ohne eine Zwischenrechnung zu machen.

Eure Ausführungen werde ich aber noch mal in Ruhe sacken lassen und 
verarbeiten. Wird sicherlich auch bei mir nur eine Frage der Gewöhnung 
sein :)

Cheers,

von Thomas E. (picalic)


Bewertung
1 lesenswert
nicht lesenswert
Außerdem gibt es binäre Schreibweise im offiziellen C-Standard auch gar 
nicht. Die "0bxxxx"-Schreibweise ist eher eine Erweiterung der 
µC-Compilerbauer.

: Bearbeitet durch User
von Peter D. (peda)


Bewertung
1 lesenswert
nicht lesenswert
Chris D. schrieb:
> Aber man sieht, dass mit der zunehmenden Anzahl an Bits das Ganze
> unleserlich wird.

Man könnte sich dafür ein Macro schreiben:
1
#define  BIN16(a,b,c,d) (0b##a##b##c##d)
2
3
int j = BIN16(0100,0010,1000,0001);

von Chris D. (myfairtux) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Peter D. schrieb:
> Chris D. schrieb:
>> Aber man sieht, dass mit der zunehmenden Anzahl an Bits das Ganze
>> unleserlich wird.
>
> Man könnte sich dafür ein Macro schreiben:

Schöne Idee :-)

Aber dadurch wird es auch weniger leserlich.

Vielleicht einfach eine (etwas längere) Tabelle mit defines, zumindest 
bis 16 Bit?
1
#define b0000_0000_0000_0000 0x0000
2
...
3
#define b1111_1111_1111_1111 0xFFFF

Wie schnell ist der Präprozessor? ;-)

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Bewertung
-1 lesenswert
nicht lesenswert
Peter D. schrieb:
> Man könnte sich dafür ein Macro schreiben:

 Ja, habe ich auch.
 Nibbles sind ungefähr 100 Mal übersichtlicher als Bytes.


Chris D. schrieb:
> Aber dadurch wird es auch weniger leserlich.

 Nein, im Gegenteil (zumindest für mich).

 P.S.
 Man kann es natürlich auch so schreiben:
1
 int j = BIN16(0100, 0010, 1000, 0001);

: Bearbeitet durch User
von Dieter W. (dds5)


Bewertung
0 lesenswert
nicht lesenswert
Chris D. schrieb:
> Vielleicht einfach eine (etwas längere) Tabelle mit defines, zumindest
> bis 16 Bit?
> #define b0000_0000_0000_0000 0x0000
> ...
> #define b1111_1111_1111_1111 0xFFFF

LOL
etwas länger ist gut. ;-))

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]
  • [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.