Pregunta

Estoy escribiendo algún tipo de software que cada bit debe ser exacta (que es para la CPU), de modo __packed es muy importante.

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;

que es mi estructura y unión. No funciona sin embargo:

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;

debe crear el mismo uint32. Pero no crean lo mismo.

¿Hay algo que no puedo ver que está mal con mi sindicato?

¿Fue útil?

Solución

Su estructura tiene sólo 31 bits

Otros consejos

AFAIK, el orden en que se almacenan los bits en el struct está definido por el estándar C99 (y el estándar C89 también). Lo más probable, los bits están en el orden inverso de lo que esperaba.

Usted debería haber mostrado el resultado que tienes, así como el resultado que esperaba - nos ayudaría con el diagnóstico. El compilador utiliza la plataforma y se ejecuta en también podrían ser significativos.


En MacOS X 10.4.11 (PowerPC G4), este código:

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

produce los resultados mostrados:

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

Con el orden de los campos invierte, el resultado es casi más explicable:

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

Esto da el resultado:

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

El primer resultado tiene un E como el último dígito hexadecimal ya que el bit menos significativo no se utiliza, ya que la estructura del campo de bits tiene sólo 31 bits definidos ..

Si la posición exacta de bits importa, lo más seguro es explícita de embalaje y desembalaje de la estructura en una matriz de caracteres sin signo. Todo lo demás es demasiado dependiente de la implementación.

En referencia a cualquier persona que pudiera encontrar esto, pruebe el atributo embalado:

struct __attribute__((packed)){

}

Usted no menciona que se están limpiando los restos de la estructura de antemano, ¿está seguro de que no está terminando con trozos sobrantes de basura en el primer caso?

// maybe try this
page_union_t p = {0};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top