Hallo, wie kann ich in C die 8 Bits eines Bytes mit Namen versehen und diese dann gezielt mit dem Namen lesen, setzen, löschen? uint8_t Status; Status soll bestehen aus: Platzhalter0 für bit0 Platzhalter1 für bit1 ... Platzhalter7 für bit7 Damit ich dann das Bit der Übersichtlichkeit mit Status.Platzhalter x lesen, setzen, löschen kann? Beispiele: Status.Platzhalter1=0; // löscht Bit1 aus Byte Status if (Status.Platzhalter0==1) { // Wenn Bit0 aus Byte Status = 0 dann... Lg Andreas
Mit __ attribute__(( _ packed_)) stehen deine Bits dann auch compilerunabhängig ordentlich in Reihe da wo Du die vermutest, falls Du mit memcpy auf dein struct zugreifen möchtest.
:
Bearbeitet durch User
Aber aufgepaßt: der C-Standard definiert nicht, wie die benannten Bits im Byte angeordnet werden. Das taugt also nicht für irgendeine Art von externem Datentausch, auch nicht zum Interfacen von Registern, sondern rein zur programm-internen Datenverarbeitung. Alles, was extern geht, macht man daher über Bitmasken. Der Hinweis auf "packed" ist falsch, denn der sorgt keineswegs für die Anordnung von Bits, sondern dafür, daß bei structs/unions (das ist was anderes als Bitfields) keine Pad-Bytes eingefügt werden. Compilerunabhängig ist das schon deswegen nicht, weil es kein Teil des C-Standards ist.
Wieso sind Bitfields kein Struct? https://gitlab.com/aIecxs/w211-ac-control/-/blob/main/w211_can_b.h#L47 ohne packed funktioniert _das_ nicht... ich hab mir den Wolf gesucht bis ich den Fehler gefunden hatte! https://gitlab.com/aIecxs/w211-ac-control/-/blob/main/pwm_can.ino#L82 Dann war es prozessorunabhängig. Beitrag "Was packt _attribute_ packed ?"
:
Bearbeitet durch User
Alexander schrieb: > Wieso sind Bitfields kein Struct? Weil die Anmerkung hier nach der Anordnung der einzelnen Bits war, nicht nach eventuellem Padding zwischen den zugrundeliegenden Integern. Die Anordnung der benannten Bits innerhalb der Integer ist nicht Compiler-unabhängig, auch nicht mit packed. Deswegen nutzt man Bitfields gerade dort nicht, wo sie verführerisch aussehen: Register-Definitionen, Mapping vom Kommunikationsstrukturen / Messages auf Bits und dergleichen. Zu Packed siehe: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#Common-Type-Attributes
Nein, meine Anmerkung bezog sich auf das Padding, deswegen auch __ attribute__(( _ packed_)). Endianness innerhalb eines "Bytes" hast Du Dir selbst dazu gedichtet. Aber danke für den Hinweis. P.S. In meinem Beispiel findest Du auch Bitfelder mit 3, 12 oder 14 Bits. Diese lassen sich schlecht in Bytes aufteilen. Deswegen nannte ich sie "Bits" konnte schlecht "Bytes" dazu sagen.
:
Bearbeitet durch User
Alexander schrieb: > Endianness innerhalb eines "Bytes" hast Du > Dir selbst dazu gedichtet. Ist das so? Du schriebst: > Mit __ attribute__(( packed)) stehen deine Bits dann auch > compilerunabhängig ordentlich in Reihe da wo Du die vermutest Und dem ist eben nicht unbedingt so. Es geht auch nicht um Endianess dabei, zumal die bei einem uint8_t wie im Ausgangsposting sowieso keine Rolle spielt, sondern der Compiler darf die Bits einsortieren, wie er lustig ist. Also bei uint8_t ist 01234567 genauso möglich wie 76543210. Genauso erlaubt wäre sogar z.B. 05271634. Manche Compiler haben Optionen, wie sie Bitfelder sortieren sollen, aber das ist eben nicht compiler-unabhängig.
Das Padding bestimmt der Compiler. Dann, und nur dann stehen die "Bytes" (Bits, Bitfelder, Integer, Bools, whatever) ordentlich in Reihe so dass man mit memcpy auch auf die Structs zugreifen kann, wenn das Padding eliminiert wurde. Ich kann Dir versichern dass mein Code ohne __ attribute__(( _ packed_)) nicht funktioniert hat.
Alexander schrieb: > Das Padding bestimmt der Compiler. Dann, und nur dann stehen die > "Bytes" (Bits, Bitfelder, Integer, Bools, whatever) ordentlich in Reihe Sicher. Nur der Inhalt ist eben in seiner Reihenfolge nicht vom C-Standard definiert. Deswegen nutzt man das nicht für Mapping auf Register, Messages und dergleichen, wenn man's portabel halten möchte. Daß Du mit "packed" eventuelle Lücken eliminiert hast, sagt nichts über die Reihenfolge der Bits aus.
Deswegen habe ich die Reihenfolge der Bits die mich interessieren _vorher_ als Bools im Struct festgelegt. Diese Reihenfolge stimmt sehr wohl (mit __ attribute__(( _ packed_))). Warum sollte das nicht portabel sein?
Alexander schrieb: > Deswegen habe ich die Reihenfolge der Bits die mich interessieren > vorher als Bools im Struct festgelegt. Eben nicht. Die Reihenfolge, in der Du die Bits innerhalb eines Basistyps (hier uint8_t) hinschreibst, haben keinen definierten Bezug dazu, wo sie innerhalb des uint8_t dann landen. Siehe: Beitrag "Re: Einzelbits in Byte Namen zuweisen und auswerten" Das verwechselst Du mit structs ohne Bitfields, wo die Reihenfolge der Deklaration dann mit der im Speicher übereinstimmt, minus padding (bzw. plus packed).
Alexander schrieb: > Warum sollte das nicht portabel sein? Ach ja: weil der C-Standard das bei Bitfields nicht definiert.
Andreas schrieb: > wie kann ich in C die 8 Bits eines Bytes mit Namen versehen und diese > dann gezielt mit dem Namen lesen, setzen, löschen? Im Prinzip garnicht. Es ist bei den meisten Architekturen immer eine Folge von: - Byte laden - Byte verändern - Byte zurückschreiben erforderlich. Zumindest. Kann auch sein, daß es nur 16 Bit-weise oder gar 32 Bit-weise geht - je nach Plattform. Eine Ausnahme sind z.B. die PIC16, wo man mit einem Maschinenbefehl ein Bit in einem Byte abfragen oder verändern kann. Auch die 8051 Architektur sieht so etwas für einige Bereiche im RAM vor, aber so etwas hat keinen Eingang in C oder eine andere maschinenunabhängige Programmiersprache gefunden. Damit bleibt dir immer nur die Abfolge Laden/Verändern/Speichern des gesamten Bytes übrig. Ganz egal, ob du das nun in irgend eine Verpackung tust oder nicht. Für gewöhnliche Bytes im RAM geht das ja, aber bei Registern in der Peripherie geht das oftmals nicht so, genaueres siehe Manual zum Chip. W.S.
W.S. schrieb: > Es ist bei den meisten Architekturen immer eine Folge von: > - Byte laden > - Byte verändern > - Byte zurückschreiben > erforderlich. Was auf solchen Architekturen übrigens den Nebeneffekt hat, daß selbst eine Zuweisung eines Bits nicht-atomar ist, was bei Betrachten des Quelltextes aber nicht gleich auffällt, wenn das eine Zuweisung an ein Bitfield ist.
Nop schrieb: > Das verwechselst Du mit structs ohne Bitfields, wo die Reihenfolge der > Deklaration dann mit der im Speicher übereinstimmt, minus padding (bzw. > plus packed). Ich verwechsele hier gar nichts. Du redest von der Endianness eines uint8_t. Ich rede von einem Bitfield Struct mit Booleans. Wenn Dir die Endianness nicht vorher bekannt ist, dann musst Du es halt doppelt definieren (Habe ich nie gebraucht):
1 | typedef struct Status_t { |
2 | #if __BYTE_ORDER == __LITTLE_ENDIAN |
3 | bool Platzhalter0 : 1; |
4 | bool Platzhalter1 : 1; |
5 | bool Platzhalter2 : 1; |
6 | bool Platzhalter3 : 1; |
7 | bool Platzhalter4 : 1; |
8 | bool Platzhalter5 : 1; |
9 | bool Platzhalter6 : 1; |
10 | bool Platzhalter7 : 1; |
11 | #elif __BYTE_ORDER == __BIG_ENDIAN |
12 | bool Platzhalter7 : 1; |
13 | bool Platzhalter6 : 1; |
14 | bool Platzhalter5 : 1; |
15 | bool Platzhalter4 : 1; |
16 | bool Platzhalter3 : 1; |
17 | bool Platzhalter2 : 1; |
18 | bool Platzhalter1 : 1; |
19 | bool Platzhalter0 : 1; |
20 | #endif |
21 | } __attribute__((__packed__)) Status_t; |
Willst Du mir jetzt sagen GNU ist kein Standard? Mit welchem Compiler arbeitest Du? Funktioniert der Code bei Dir nicht?
:
Bearbeitet durch User
Alexander schrieb: > Du redest von der Endianness eines uint8_t. Nein, rede ich nicht, zumal ein uint8_t auch keine Endianess hat. Endianess ist was völlig anderes, wie ich bereits mehrfach erwähnt habe. Ich rede davon, daß das erste Bit in Deinem Bitfeld auf einem uint8_t nicht auf Bit 0 des uint8_t liegen muß, und auch nicht auf Bit 7, sondern auf irgendeinem Bit liegen kann. Das steht dem verwendeten Compiler völlig frei (und hat mit Plattform-Endianess nichts zu tun), auch wenn in der Praxis von unten oder von oben her aufgefüllt wird. > Willst Du mir jetzt sagen GNU gcc ist kein Standard? Standard ist allein der C-Standard, sonst gar nichts, und der sagt dazu halt nichts. > Funktioniert der Code bei Dir nicht? Nicht portabel != funktioniert nicht. Völlig anderes Problem.
Nop schrieb: > Ich rede davon, daß das erste Bit in Deinem Bitfeld auf einem uint8_t > nicht auf Bit 0 des uint8_t liegen muß, und auch nicht auf Bit 7, > sondern auf irgendeinem Bit liegen kann. Nennen wir es Bit-endianness. Praktisches Beispiel bitte. Reden wir hier noch von Mikrocontrollern?
:
Bearbeitet durch User
Alexander schrieb: > Praktisches Beispiel bitte. Es ist im C-Standard nicht definiert, wie die Reihenfolge ist, folglich Compiler-spezifisch, folglich nicht portabel. Es kann sich also nicht nur von Compiler zu Compiler, sondern auch mit einem Compiler-Update ändern. Das ist elementare Logik und nichts, was ein "Beispiel" bräuchte. Kannst Dir ja ansonsten mal die Kommentare bei https://embeddedgurus.com/stack-overflow/2009/10/effective-c-tip-6-creating-a-flags-variable/#comments ansehen, wo Leute schon mit sowas reingefallen sind. Oder halt auf SO: https://stackoverflow.com/questions/55823879/should-i-use-bit-fields-for-mapping-incoming-serial-data
Achso, und "Bit-Endianess" ist es auch nicht, weil es mit der CPU nichts, aber auch gar nichts zu tun hat. Es liegt einzig am Compiler, wie er Bitfields implementiert.
Einfach mal hier schauen: https://en.cppreference.com/w/c/language/bit_field (unter Notes). Daher für bspw. explizites Bit-Placement unbrauchbar bei etwa µC-Registern. Das heißt aber nicht, dass es nicht zufälligerweise funktionieren kann. Ist aber eben IB und damit eben ein moving-target ;-) Hinzu kommt wie oben schon gesagt wurde, dass meistens das als RMW (nicht atomar) umgesetzt werden (muss), sofern der µC dafür keine Unterstützung mitbringt (bit-set-Befehle wie etwa AVR SBI/CBI oder set-reset-register)
Meine Lösung ist folgende: in der .h:
1 | #define SETBIT(REG, PIN) ((REG) |= (uint32_t) 1 << (PIN)) |
2 | #define CLEARBIT(REG, PIN) ((REG) &= ~((uint32_t) 1 << (PIN))) |
3 | #define CHANGEBIT(REG, PIN, WERT) ((WERT) ? SETBIT((REG), (PIN)) : CLEARBIT((REG), (PIN))) |
4 | #define READBIT(REG, PIN) (((REG) >> (PIN)) & 1) |
5 | |
6 | // und die Bits definieren mit: |
7 | // LEDBYTE (Byte) |
8 | #define FAULT_LED 3 |
9 | #define OPERATION_LED 6 |
10 | #define NETWORK_LED 5 |
11 | #define HEATER_LED 4 |
// aufrufen in C dann mit
1 | READBIT(LEDBYTE, HEATER_LED) |
Ich würde alle Zugriffe eher in (Inline)Funktionen kapseln. Dann kann man den nichtatomaren Aufruf gleich noch mit einbauen.
1 | GetData1(structx) |
2 | SetData1(structx, data) |
3 | IsBusy(structx) |
4 | //Usw
|
Falls mann doch auf alle guten Ratschläge pfeift und die Bit Position wichtig ist: In jeder Übersetzungseinheiten per static_assert die structx Architektur checken. So habe ich es früher gemacht und tatsächlich bei einem Compilerwechsel den gefährlichen Zustand entdeckt.
Na dann viel Spaß mit den Bitmasken im C Standard. Ich weise darauf hin meine .h ist autogeneriert ;) für den Arduino reichts
> typedef struct Status_t { > bool Platzhalter0 : 1; > ... > } __attribute__((_packed_)) Status_t; Hier liegt das Problem doch beim "bool". Dessen Größe ist implementation-defined (und hat sich beim GCC im Laufe der Zeit auch verändert). Wenn der z.B. als "typedef { false, true } bool;" definiert ist, liefert "sizeof Status_t" ohne packed 4, mit packed 1. Wo die Bits dabei landen, weiß der Deibel.
foobar schrieb: > Hier liegt das Problem doch beim "bool". Ist seit C99 explizit zugelassen neben den drei anderen DT unsigned, signed und int.
Alexander schrieb: > Wo sollen die landen bei "mit packed 1" ;) Mal ne ernste Frage: Wozu soll dieser Diskurs gut sein? Ist es nur zwecks Besserwisserei oder steckt ein ernstes Anliegen dahinter? In letzterem Falle wäre die Frage, ob es irgendwelche Innereien eines Lowlevel-Treibers betreffen sollen oder ob es Signale wie "Lampe_Ein" oder "Schotten_dicht" sein sollen, die in irgendwelchen Algorithmen verwendet werden sollen. Sind es Treiber-Innereien, dann ist das Arbeiten mit #define Einschaltbit (1<<7) oder so angesagt. Sind es Signale wie genannt, dann ist angesagt, sowas in einzelne Funktionen zu verpacken (a la void Lampe_Ein(void) oder so) und in eine separate Quelle zu verfrachten. Dann ist die Firmware auch mit geringem Aufwand portabel. Und daß das Herumhampeln mit Bitfeldern eine heikle Sache ist, wurde dir ja bereits gesagt. W.S.
Warum sprichst du mich an? Ich habe nur einen Tipp gegeben. Die Besserwisserei (geht's nicht immer darum?) dass die von mir bevorzugte Lösung hypothetisch auf irgendeinem Mikrocontroller mal nicht funktionieren könnte, weil nicht portabel kein C Standard, nicht definiert, kein GNU compiler benutzt, bla bla habe nicht ich losgetreten.
Alexander schrieb: > Na dann viel Spaß mit den Bitmasken im C Standard. Ich weise darauf hin > meine .h ist autogeneriert ;) Von wem?
Ist doch alles auf gitlab. das 211_219_I_AEJ2003_X.dat file wird ausgelesen und die Structs generiert. Ein Fahrzeug hat über 50 Steuergeräte. Jede CAN ID hat eine eigene Bitstruktur und daher sein eigenes Struct. Der Aufbau ist immer gleich, daher problemlos via script generierbar. Ich hab nur 3 CAN IDs gebraucht, und selbst das wäre mir zu viel gewesen. eingelesen wird mit
1 | memcpy(&struct, msg, len); |
Mir konnte immer noch keiner sagen auf welchem Mikrocontroller das nicht funktionieren soll. Da hab ich ja richtig Glück gehabt dass es auf meinem Intel und auf dem Kinetis läuft ;)
Alexander schrieb: > Da hab ich ja richtig Glück gehabt dass es auf > meinem Intel und auf dem Kinetis läuft ;) Wenn Du bis jetzt nicht verstanden hast, was das Problem von nicht-portablem Code ist, dann wirst Du es auch nicht mehr verstehen. Ist halt mehr was für Profis.
Ich bin kein Programmierer und habe keine Anforderungen an MISRA. Und Profi bin ich erst Recht nicht, ich habe noch nie was selbst programmiert. Es macht keinen Sinn die Kontroverse aus Deinen Links hier fortzuführen, wenn schon die Profis sich uneinig sind.
Alexander schrieb: > Ich bin kein Programmierer und habe keine Anforderungen an MISRA. Und > Profi bin ich erst Recht nicht, ich habe noch nie was selbst > programmiert. Das sieht man. Allerdings machst Du dafür eine große Welle ... > Es macht keinen Sinn die Kontroverse aus Deinen Links hier > fortzuführen, wenn schon die Profis sich uneinig sind. Die Profis sind sich einig: Bit-Fields für Compiler/Architektur übergreifenden Zugriff oder Zugriff auf µC-Register sind nicht-portabel, weil IB. Man kann Glück haben - wie Du offensichtlich - doch es bleibt wackelig (sofern Du das nicht durch Zusicherungen absicherst. Da Du aber kein Programmierer bist, weißt Du auch nicht das Zusicherungen sind. Auch wieder blöd ...)
Wir sind hier aber auch im Unterforum Mikrocontroller und Elektronik, wäre nicht verkehrt anzunehmen es ginge um praktikable Ansätze im Hobbybereich :)
:
Bearbeitet durch User
Alexander schrieb: > Wir sind hier aber auch im Unterforum Mikrocontroller und Elektronik, > wäre nicht verkehrt anzunehmen es ginge um praktikable Ansätze im > Hobbybereich :) Die praktikablen Ansätze wurden alle schon genannt.
Ja, und ich finde eben den hier ganz praktikabel: Nop schrieb: > https://embeddedgurus.com/stack-overflow/2009/10/effective-c-tip-6-creating-a-flags-variable
Alexander schrieb: > Ja, und ich finde eben den hier ganz praktikabel: > Nop schrieb: >> > https://embeddedgurus.com/stack-overflow/2009/10/effective-c-tip-6-creating-a-flags-variable Sicher. Du schickst etwas von diesen Bits von einem µC zu einem anderen µC? Du benutzt dies um auf Register eines µC oder Peripherie zu zu greifen? Wie beantwortest Du dieses Fragen?
Wenn Du Steuergeräte im Auto als µC bezeichnen willst, mit Ja (1) Für die zweite Frage wäre es gut mal einen realen Fall aus der Praxis zu zeigen, wo das ein tatsächliches Problem ist. (Link reicht)
:
Bearbeitet durch User
Alexander schrieb: > Wenn Du Steuergeräte im Auto als µC bezeichnen willst, mit Ja (1) Bingo. Dann funktioniert der Datenaustausch eben nur mit viel Glück. > Für die zweite Frage wäre es gut mal einen realen Fall aus der Praxis zu > zeigen, wo das ein tatsächlich ein Problem ist. Hast Du das immer noch nicht verstanden? Im Register des µC ist Bit0 für den Reset einer internen Peripherie zuständig, und Bit1 ist ein Status-Bit. Du hast zwar in dem Bit-Field die Bits nun von 0 bis 7 angeordnet, der Compiler platziert aber das Element 0 nicht bei Bit0 sondern irgendwo anders. Dann geht Dein vermeintlicher Reset der Peripherie ggf. nicht, weil Du irgendein anderes Bit (evtl. das o.g. Status-Bit) erwischt. Und mit der nä. Compiler-Version ist es wieder anders.
Wilhelm M. schrieb: > der Compiler platziert aber das Element 0 nicht bei Bit0 sondern > irgendwo anders. > [...] Und mit der nä. Compiler-Version ist es wieder anders. Was gibt's daran nicht zu verstehen? Ich habe aber nach einem realen Fall gefragt, wo einen das "Glück" verlässt. Welcher µC, welcher Compiler (beachte: __ attribute__(( _ packed_)) = GNU Extension)??
Alexander schrieb: > Wilhelm M. schrieb: >> der Compiler platziert aber das Element 0 nicht bei Bit0 sondern >> irgendwo anders. >> [...] Und mit der nä. Compiler-Version ist es wieder anders. > > Was gibt's daran nicht zu verstehen? Keine Ahnung ;-) > Ich habe aber nach einem realen > Fall gefragt, wo einen das "Glück" verlässt. Welcher µC, welcher > Compiler (beachte: __ attribute__(( _ packed_)) = GNU Extension)?? Die Syntax _attribute_ ist GNU spezifisch. Du kannst aber mit C23 die genormte Syntax verwenden:
1 | [[ attr ]] |
Damit bleibt es aber immer noch IB. Außerdem hat "packed" NICHTS mit der Anordnung der Bits zu tun, das hast Du immer noch nicht verstanden. Dazu hatte ich oben einen Link auf den Standard gepostet wo das drin steht.
:
Bearbeitet durch User
Wilhelm M. schrieb: > Außerdem hat "packed" NICHTS mit der Anordnung der Bits zu tun Es korreliert aber! Und mir hat noch keiner den schwarzen Schwan gebracht. Im übrigen habe ich "Bytes" als "Bits" - im Sinne von Bitgruppe - bezeichnet. Gemeint war, dass die Struct Member nur gepackt am richtigen Offset zu finden sind. Und diese können aus nur 1 Bit bestehen. Das ursprüngliche Post #4 war flapsige Umgangssprache und Nop hat das erstmal korrigiert/thematisiert. Über die Anordnung der EINZELNEN Bits INNERHALB eines Boolean (oder uint8_t Platzhalter0:1;) habe ich mir vorher keine Gedanken gemacht... das hat "zufällig" über die Byte Endianness funktioniert. Alexander schrieb: > Wo sollen die landen bei "mit packed 1" ;)
:
Bearbeitet durch User
Alexander schrieb: > Wilhelm M. schrieb: >> Außerdem hat "packed" NICHTS mit der Anordnung der Bits zu tun > > Es korreliert aber! Jein. Natürlich hat das padding Einfluss. Aber davon sprechen wir hier gar nicht, sondern einzig allein über die Bit-Anordnung im underlying-type. Aus der Bemerkung ziehe ich den Schluss, dass Du es immer noch nicht verstanden hast, den Unterschied zwischen padding und Bit-Anordnung. > Im übrigen habe ich "Bytes" als "Bits" - im Sinne von Bitgruppe - > bezeichnet. Gemeint war, dass die Struct Member nur gepackt am richtigen > Offset zu finden sind. Und diese können aus nur 1 Bit bestehen. Das > ursprüngliche Post #4 war flapsige Umgangssprache und Nop hat das > erstmal korrigiert/thematisiert. Über die Anordnung der EINZELNEN Bits > INNERHALB eines Boolean (oder uint8_t Platzhalter0:1;) habe ich mir > vorher keine Gedanken gemacht... das hat "zufällig" über die Byte > Endianness funktioniert. Im übrigen ist uint8_t strenggenommen auch nicht zulässig als underlying-type, sondern nur int, signed, unsigend und bool (s.a. C-Standard).
Man kann das Ganze ungeheuer kompliziert betrachten. Man kann aber auch einfach auf avr-gcc testen und dann die gültige Bitorder anwenden:
1 | To determine the compiler is avr-gcc, you need to test for 2 macros __GNUC__ and __AVR__ |
Die avr-gcc Entwickler sind recht konservativ, sie werden niemals die ungünstige Vorbelegung von R0, R1 ändern. Daher werden sie erst recht nicht die Bitorder ändern.
Peter D. schrieb: > Man kann das Ganze ungeheuer kompliziert betrachten. > Man kann aber auch einfach auf avr-gcc testen und dann die gültige > Bitorder anwenden: >
1 | > To determine the compiler is avr-gcc, you need to test for 2 macros |
2 | > __GNUC__ and __AVR__ |
3 | > |
Das Thema static_assert o.ä. wurde doch auch schon längst genannt. Das mit AVR hilft ihm aber auch nicht wirklich, weil er ja Intel und ARM kommunizieren lässt ;-)
:
Bearbeitet durch User
Ich habe verstanden dass mein Workaround keine portable Problemlösung im C Standard ist. Danke für den Hinweis
Nicht aus Provokation sondern aus Interesse und Spieltrieb: Kennt jemand eine konkrete Compilerversion, die die Bitfields Reihenfolge verändert?
:
Bearbeitet durch User
Beitrag #7214101 wurde vom Autor gelöscht.
Klaus H. schrieb: > Nicht aus Provokation sondern aus Interesse und Spieltrieb: > > Kennt jemand eine konkrete Compilerversion, die die Bitfields > Reihenfolge verändert? Bei ARM64 ist es konfigurierbar/veränderbar: https://github.com/ARM-software/abi-aa/blob/60a8eb8c55e999d74dac5e368fc9d7e36e38dda4/aapcs64/aapcs64.rst#8182bit-field-extraction-expressions Der Compiler ist demgegenüber agnostisch und das ABI kann umschalten ;-)
:
Bearbeitet durch User
Danke. Hast du auch ein Beispiel in dem aus Optimierungszwecken die Bitreihenfolge sich ändert?
Klaus H. schrieb: > Danke. > > Hast du auch ein Beispiel in dem aus Optimierungszwecken die > Bitreihenfolge sich ändert? Beispiel wegen Optimierung, also durch bspw. Umschalten von -O0 auf -O3 ?: mir ist kein Beispiel bekannt.
Klaus H. schrieb: > Hast du auch ein Beispiel in dem aus Optimierungszwecken die > Bitreihenfolge sich ändert? Ich häng' mich als Laie mal rein. Ich könnte mir vorstellen, dass Bitmanipulationen, die man günstig mit speziellen Befehlen für Halbbytes macht, eine solche Neuanordnung zur Folge haben.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.