Servus,
ich habe ein Byte zur Zuweisung von Funktionen das ich vorab im Code
setzen/ändern möchte.
Im Programm soll eine Schleife so oft laufen, wie Einsen in dem Byte
stehen.
Wie kann ich per Makro o.ä. die Anzahl der gesetzten Bits in einem Byte
rausfinden?
Wenn das nur zum Compilieren benutzt wird, kannst du lieber die Bits
selber zählen. Das ist einfacher.
Wenn es im Programm auch variable eingesetzt werden soll, nimmst du eine
Schleife von 1 bis 128 und multiplizierst den Schleifenwert immer mit 2.
Das ist dann eine Schleife, die 8 Mal durchlaufen wird.
In der Schleife vergleichst ("Logisches UND") du den Schleifenzähler mit
deinem Byte und jedes Mal, wenn wenn der Vergleich positiv war, zählst
du eine weitere Variable hoch.
Macros mögen keine Rekursion, also lohnt der K&R BitCOunt nicht, man
kann es auf die übersichtliche Art machen:
#define bits7(x) (x&0x80?1:0)
#define bits6(x) (x&0x40?1:0)+bits7(x)
#define bits5(x) (x&0x20?1:0)+bits6(x)
#define bits4(x) (x&0x11?1:0)+bits5(x)
#define bits3(x) (x&8?1:0)+bits4(x)
#define bits2(x) (x&4?1:0)+bits3(x)
#define bits1(x) (x&2?1:0)+bits2(x)
#define bits(x) ((x&1?1:0)+bits1(x))
Anwendung:
n = bits(0x22)
MaWin schrieb:
> Macros mögen keine Rekursion, also lohnt der K&R BitCOunt nicht, man> kann es auf die übersichtliche Art machen:>> #define bits7(x) (x&0x80?1:0)> #define bits6(x) (x&0x40?1:0)+bits7(x)> #define bits5(x) (x&0x20?1:0)+bits6(x)> #define bits4(x) (x&0x11?1:0)+bits5(x)> #define bits3(x) (x&8?1:0)+bits4(x)> #define bits2(x) (x&4?1:0)+bits3(x)> #define bits1(x) (x&2?1:0)+bits2(x)> #define bits(x) ((x&1?1:0)+bits1(x))>> Anwendung:>> n = bits(0x22)
Über diese Brücke würde ich nicht unbedingt gehen.
> Über diese Brücke würde ich nicht unbedingt gehen.
Mal abgesehen von 0x11,
Wir warten auf deinen besseren Vorschlag, aber da kommt sicher Nichts.
Den 4-zeiler hab ich wegen Unübersichtlichkeit absichtlich nicht
gebracht.
A.K. Vorschlag funktioniert doch wunderbar, ist nachvollziehbar und
einfach zu definieren und liefert wie gewünscht die Anzahl der Einsen in
einem Byte zurück. Was mehr? Es geht nur um eine
Präprozessor-Geschichte, da ist eventuelles Optimieren eh nicht so
wichtig...
Phillip Hommel schrieb:
> A.K. Vorschlag funktioniert doch wunderbar, ist nachvollziehbar und> einfach zu definieren und liefert wie gewünscht die Anzahl der Einsen in> einem Byte zurück. Was mehr? Es geht nur um eine> Präprozessor-Geschichte, da ist eventuelles Optimieren eh nicht so> wichtig...
Ich denke mit Optimieren hat das wenig zu tun.
Prärpozessor Makros sind generell gefährlich und man muss vorsichtig
sein.
Wenn schon, würde ich noch eine inline Funktion drüberstülpen.
Phillip Hommel schrieb:
> Servus,> ich habe ein Byte zur Zuweisung von Funktionen das ich vorab im Code> setzen/ändern möchte.> Im Programm soll eine Schleife so oft laufen, wie Einsen in dem Byte> stehen.> Wie kann ich per Makro o.ä. die Anzahl der gesetzten Bits in einem Byte> rausfinden?
Bits zählt man am einfachsten so:
@ Johann,
ich möchte aber nicht zur Laufzeit sondern vorab die Bitzahl wissen da
diese zur Laufzeit fix ist.
Spezialfälle kommen bei mir nicht vor da ich das ganze nur an drei oder
vier stellen benutze und ich da nur ein fertiges Byte zw 0x00 und 0xff
übergebe.
Da funktioniert das simple Makro doch hervorragend.
Phillip Hommel schrieb:
> @ Johann,> ich möchte aber nicht zur Laufzeit sondern vorab die Bitzahl wissen da> diese zur Laufzeit fix ist.
Dann verwende __builtin_popcount. Wenn der Wert zur Compilezeit bekannt
ist, wertet GCC das aus und ersetzt es durch die entsprechende
Konstante.
Da Makro oben von A.K. müsste auch gehen; gcc sollte den entstehenden
recht komplexen Ausdruck zu ner Konstanten falten (falls ihm nicht
irgendwelche "Optimierungs-Kapriolen" zu Kopfe steigen).
Johann
MaWin schrieb:
>> Über diese Brücke würde ich nicht unbedingt gehen.>> Mal abgesehen von 0x11,> Wir warten auf deinen besseren Vorschlag, aber da kommt sicher Nichts.> Den 4-zeiler hab ich wegen Unübersichtlichkeit absichtlich nicht> gebracht.
Spar dir solches Gesülze und probier mal folgendes mit deiner Variante:
> probier mal folgendes mit deiner Variante
Brauch ich nicht, braucht Philipp nicht,
aber du kannst gerne Klammern spendieren.
Dein Beitrag war für'n Arsch.
hört auf euch zu anzuflamen und bleibt sachlich
um das argument gehören immer klammern, ich würd also noch mehr setzen.
Selbst wenn es zum derzeitigen Zeitpunkt wirklich nur für einfache
Konstanten genutzt wird.
Beim nächstem mal steckt man vielleicht was anderes rein und hat die
Randbbedingungen schon wieder vergessen
1
#define bits7(x) ((x)&0x80?1:0)
2
#define bits6(x) ((x)&0x40?1:0)+bits7(x)
3
#define bits5(x) ((x)&0x20?1:0)+bits6(x)
4
#define bits4(x) ((x)&0x11?1:0)+bits5(x)
5
#define bits3(x) ((x)&8?1:0)+bits4(x)
6
#define bits2(x) ((x)&4?1:0)+bits3(x)
7
#define bits1(x) ((x)&2?1:0)+bits2(x)
8
#define bits(x) (((x)&1?1:0)+bits1(x))
obwohl ich das ganze in ein define packen würde, um den namespace nicht
so vollzumüllen
Edit:
bits ist vielleicht auch nicht der geeigneteste Name dafür.
Hallo Karl heinz,
> Wenn schon, würde ich noch eine inline Funktion drüberstülpen.
Den Tip werde ich mir mal merken. Das ist eigentlich eine recht elegante
Lösung für gefährliche Macros, die ich bisher nicht kannte. Und eine
gewisse Typensicherheit bekommt das ganze auch noch. DANKE!
Axel
Wobei man das dann auch nicht drüberstülpen muss, sondern gleich so ohne
Verwendung eines Makros realisieren kann. Das hat neben einigen
Vorteilen aber auch Nachteile.
Eine reine Konstantenrechnung im Makro wird immer vom Compiler fertig
ausgewertet, eine Inline-Funktion abhängig von Optimierungsgrad,
Compilerversion und Wasserstand. Und das Ergebnis einer
Konstantenrechnung kann man in einem #if abfragen.
Hallo A. K.,
das mir der Auswertung von Inline-Funktion durch den Compiler ist so
eine Sache. Eigentlich sollte er das machen und eigentlich sollte der
Optimierer das erkennen. Aber ich habe schon zu oft gesehen, dass
Compiler das nicht machen bzw. schnell bei Verschachtelungen aufgeben.
Und da hilft es dann auch nicht, dem Compiler dazu zu zwingen mit
irgendwelchen Aufruf-Parametern oder Funktions-Attributen.
Ausserdem kommt auch noch hinzu, dass bei einem Debug-Build
normalerweise nicht Optimiert wird, damit ich Dinge nachvollziehbar
bleiben. Trotzdem sollten aber so "einfache" Sachen wie das Zählen von
Bits oder das berechnen von Offsets vom Compiler erledigt werden - sonst
passt der Code einfach nicht in den Chip. Dann sind Macro die bessere
Wahl und ein inline-Wrapper macht das ganze noch etwas sicherer.
Aber über sowas kann man sich sowieso vortrefflich streiten. Und
vielleicht wird das mit LLVM Compilern irgendwann mal besser .... ;)
Axel