Es geht um eine Popcount-Routine mit Bit-Twiddling. Die funktioniert
auch, aber nicht mehr, wenn man die Konstanten alle mit dem Suffix UL
als unsigned long markiert, obwohl das gehen sollte. Gemäß integer
promotion müßte das IMO ohnehin nach UL (32 bit) promoted werden.
Drei Versionen: die erste ohne Suffixe, die zweite soweit, daß es noch
geht, die dritte geht nicht mehr. Also wenn man in der Zeile mit der
Multiplikation nicht nur U, sondern UL hinzufügt (egal zu welcher der
Konstanten), scheitert es mit verkehrtem Ergebnis.
Getestet mit GCC 9.3.0 64 Bit unter Linux, keine Warnungen erschienen.
Die letzte Multiplikation nutzt die modulare Arithmetik eines 32 Bit
Integers aus, und UL macht das eben kaputt weil
Egon D. schrieb:>> Getestet mit GCC 9.3.0 64 Bit unter Linux,> .........................^^^^^^
Egon D. schrieb:> Nop schrieb:>>> UL (32 bit)>> ???>>> Getestet mit GCC 9.3.0 64 Bit unter Linux,> .........................^^^^^^
Ah, danke. Mir war nicht klar, daß "long" 64 Bit hat unter einem
64-Bit-Linux. Der Code kam von einem Windowssystem mit 64 Bit, wo "long"
nur 32 Bit hat.
Rolf M. schrieb:> Wenn's ein uint32_t sein soll, nimmt man am besten> UINT32_C(0x55555555).> Dann macht der Präprozessor den auf dem System passenden Suffix draus.
Auch ein interessanter Tip, gerade für solche Bithacks.
Wobei einfach nur U als Suffix ja im Normalfall ohnehin passend promoten
sollte, selbst wenn man auf einem System mit int als 16 Bit ist, da
müßte das dann nach unsigned long gehen. Also, auch ohne daß es wie hier
zusammen mit einem uint32_t in einem Ausdruck steht.
Programmierer schrieb:> Alternativ: __builtin_popcount benutzen...
Das mache ich schon, wenn eine entsprechende Build-Option mitgegeben
wurde. Das Bitgeschubse ist der Fallback, wenn nicht.
Nop schrieb:> Rolf M. schrieb:>> Wenn's ein uint32_t sein soll, nimmt man am besten>> UINT32_C(0x55555555).>> Dann macht der Präprozessor den auf dem System passenden Suffix draus.>> Auch ein interessanter Tip, gerade für solche Bithacks.
Allgemein sind die Makros in <stdint.h> einen Blick wert. Manche sind
zwar richtig hässlich, aber wenn mans brauch ist man trotzdem froh.
Nop schrieb:> Das mache ich schon, wenn eine entsprechende Build-Option mitgegeben> wurde. Das Bitgeschubse ist der Fallback, wenn nicht.
Semi-OT: Wie machst Du die Auswahl, welche Lösung verwendet wird? Bei
mir sieht das oft unschön aus:
Walter T. schrieb:> Semi-OT: Wie machst Du die Auswahl, welche Lösung verwendet wird?
Ich verwende die portable Lösung als Default, wenn kein entsprechendes
define über die Buildchain gesetzt ist. Die Auto-Detection wie in Deinem
Beispiel nehme ich nicht, weil ich das manuell kontrollieren will.
Das brauche ich z.B., wenn ich im Mockup auf dem Host teste, der popcnt
unterstützt, aber die spätere embedded-Anwendung auf einer Plattform
laufen soll, die das nicht tut. Zugleich bekomme ich eine Vorstellung,
wieviel Geschwindigkeitsgewinn in der konkreten Anwendung denn über
natives popcnt drin wäre.