Question

J'écris un logiciel où chaque bit doit être exact (il est pour le CPU) si __packed est très important.

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;

qui est ma structure et de l'union. Il ne fonctionne pas cependant:

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;

devrait créer le même uint32. Mais ils ne créent pas la même chose.

Y at-il quelque chose que je ne vois pas qui est le problème avec mon syndicat?

Était-ce utile?

La solution

Votre struct a seulement 31 bit

Autres conseils

AFAIK, l'ordre dans lequel les bits dans la structure sont stockés est indéfini par la norme C99 (et la norme C89 aussi). Très probablement, les bits sont dans l'ordre inverse de ce que vous attendiez.

Vous devriez avoir montré le résultat que vous avez obtenu ainsi que le résultat que vous attendiez - elle nous aider au diagnostic. Le compilateur que vous utilisez et la plate-forme que vous exécutez sur pourraient être importants.


Sur Mac OS X 10.4.11 (PowerPC G4), ce 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);
}

produit les résultats présentés:

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

Avec l'ordre des champs inversé, le résultat est plus près explicables:

#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);
}

Cela donne le résultat:

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

Le premier résultat a un E, comme le dernier chiffre hexadécimal parce que le bit le moins significatif est pas utilisé, parce que la structure du champ de bits a seulement 31 bits définis ..

Si la position exacte de bits importe, votre pari le plus sûr est l'emballage et le déballage explicite de la structure dans un tableau non signé char. Tout le reste est trop dépendante de la mise en œuvre.

Pour référence à tous ceux qui pourraient trouver cela, essayez l'attribut emballé:

struct __attribute__((packed)){

}

Vous ne mentionnez pas que vous effacez les bits de la structure à l'avance, vous êtes sûr que vous n'êtes pas se retrouver avec des bits de déchets laissés dans le premier cas?

// maybe try this
page_union_t p = {0};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top