Frage

ich einige Software ich schreibe, wo jedes Bit genau sein muss (es ist für die CPU) so __packed ist sehr wichtig.

typedef union{
uint32_t raw;
struct{
    unsigned int present:1;
    unsigned int rw:1;
    unsigned int user:1;
    unsigned int dirty:1;
    unsigned int free:7;
    unsigned int frame:20;
} __packed;
}__packed page_union_t;

, dass meine Struktur und Vereinigung ist. Es ist jedoch nicht funktionieren:

page_union_t p; //.....
//This:
p.frame=trg_page;
p.user=user;
p.rw=rw;
p.present=present;
//and this:
p.raw=trg_page<<12 | user<<2 | rw<<1 | present;

sollten die gleiche Uint32 erstellen. Aber sie schaffen nicht das Gleiche.

Gibt es etwas, das ich nicht, dass mit meiner Gewerkschaft falsch sehen kann?

War es hilfreich?

Lösung

Ihre Struktur hat nur 31 Bit

Andere Tipps

AFAIK, in welcher Reihenfolge die Bits in der Struktur gespeichert werden, wird durch den C99-Standard (und der C89-Standard auch) nicht definiert. Höchstwahrscheinlich sind die Bits in umgekehrter Reihenfolge von dem, was Sie erwartet.

Sie sollten das gewünschte Ergebnis sowie das Ergebnis bekommen gezeigt Sie erwartet - es uns mit der Diagnose helfen würde. Die Compiler Sie verwenden und die Plattform, die Sie auf ausführen könnten auch von Bedeutung sein.


Auf MacOS X 10.4.11 (PowerPC G4), dieser Code:

#include <inttypes.h>
#include <stdio.h>

typedef union
{
        uint32_t raw;
        struct
        {
                unsigned int present:1;
                unsigned int rw:1;
                unsigned int user:1;
                unsigned int dirty:1;
                unsigned int free:7;
                unsigned int frame:20;
        };
} page_union_t;

int main(void)
{
        page_union_t p = { .raw = 0 }; //.....
        unsigned trg_page = 0xA5A5A;
        unsigned user = 1;
        unsigned rw = 1;
        unsigned present = 1;

        p.frame = trg_page;
        p.user = user;
        p.rw = rw;
        p.present = present;

        printf("p.raw = 0x%08X\n", p.raw);

        p.raw = trg_page<<12 | user<<2 | rw<<1 | present;
        printf("p.raw = 0x%08X\n", p.raw);

        p.raw <<= 1;
        printf("p.raw = 0x%08X\n", p.raw);
        return(0);
}

erzeugt die Ergebnisse gezeigt:

p.raw = 0xE014B4B4
p.raw = 0xA5A5A007
p.raw = 0x4B4B400E

Mit der Reihenfolge der Felder umgekehrt, ist das Ergebnis mehr ist fast erklärbar:

#include <inttypes.h>
#include <stdio.h>

typedef union
{
        uint32_t raw;
        struct
        {
                unsigned int frame:20;
                unsigned int free:7;
                unsigned int dirty:1;
                unsigned int user:1;
                unsigned int rw:1;
                unsigned int present:1;
        };
} page_union_t;

int main(void)
{
        page_union_t p = { .raw = 0 }; //.....
        unsigned trg_page = 0xA5A5A;
        unsigned user = 1;
        unsigned rw = 1;
        unsigned present = 1;

        p.frame = trg_page;
        p.user = user;
        p.rw = rw;
        p.present = present;

        printf("p.raw = 0x%08X\n", p.raw);

        p.raw = trg_page<<12 | user<<2 | rw<<1 | present;
        printf("p.raw = 0x%08X\n", p.raw);

        p.raw <<= 1;
        printf("p.raw = 0x%08X\n", p.raw);
        return(0);
}

Das gibt das Ergebnis:

p.raw = 0xA5A5A00E
p.raw = 0xA5A5A007
p.raw = 0x4B4B400E

Das erste Ergebnis hat eine E als letzten Hexadezimalzeichens weil das niedrigstwertige Bit nicht verwendet wird, da die Bit-Feldstruktur nur 31-Bit definiert hat ..

Wenn die genaue Position von Bits zählt, Ihre sicherste Wette ist explizite Packen und Entpacken der Struktur in einen unsigned char-Array. Alles andere ist auch abhängig von der Implementierung.

Als Referenz für alle, die diese finden könnte, versuchen Sie das gepacktes Attribut:

struct __attribute__((packed)){

}

Sie haben nicht erwähnen, dass Sie vorher die Bits der Struktur Entrümpelung, sind Sie sicher, dass Sie nicht mit Müll Bits übrig blieb im ersten Fall enden werden?

// maybe try this
page_union_t p = {0};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top