2016-04-08 32 views
2

i Şimdi ben bu yüzden bir saklayıcısında olarak kullanabilirsiniz bir işlev tarafından döndürülen bir gelen U8 değer dağıtmak istiyorum (U8 unsinged tamsayı 8 demektir)C Skaler tipini skaler olmayan ve geriye doğru nasıl dökerim?

typedef struct build_field{ 

    u8 build : 5; 
    u8 ability : 1; 
    u8 hability : 1; 
    u8 shinyness : 1; 

} build_field; 

kendime bir bit maskesini ilan etti.

build_field f = (build_field) func_that_returns_u8(); 

Ayrıca bunu bir u8 değerine geri çevirmek istiyorum.

u8 x = (u8) field; 

Ancak C derleyicim bu işlemlerden herhangi birini yapmama izin vermez. Sorunu nasıl düzeltebiliriz?

+0

'U8 val = 0xb5; build = val & 0x1f; yetenek = (val & 0x20) >> 5; Hability = (val & 0x40) >> 6; shinyness = (val & 0x80) >> 7; 'ya da bitleri istediğiniz sırada. – pmg

cevap

4

kullanın birlik:

union myunion 
{ 
    u8 value; 
    build_field field; 
}; 

union myunion m; 
m.value = func_that_returns_u8(); 
u8 a = m.ability; 

aksi takdirde bu işe yaramaz yapı build_field üyeleri arasında hiçbir doldurma olduğundan emin olun.

Daha hassas bir seçenek, bitleri tam sayıdan çıkarmaktır. Değerdeki bitlerin yapıdaki üyelerle aynı sırada olduğunu varsayalım. abilityhability değerlerini almak ve etmek yapmanız:

u8 value = func_that_returns_u8(); 
build_field f = { 0 }; 
f.hability = ((unsigned int)value >> 6U) & 1U; 
f.ability = ((unsigned int)value >> 5U) & 1U; 
0

Bu satır içine yerleştirilmiş olabilir, static C. Kombine bütün yapılar dönebilirsiniz de

static build_field compose_field(unsigned char uc) 
{ 
union { 
     unsigned char uc; 
     build_field bf; 
     } uni = {uc}; 
return uni.bf; 
} 
(gcc'deki -O1 ile başlar)

Kullanımı

int main(void) 
{ 
build_field val; 

val = compose_field(0xa5); // "constructor" 
printf(" {%u %u %u %u}\n" 
     , (unsigned int) val.build 
     , (unsigned int) val.ability 
     , (unsigned int) val.hability 
     , (unsigned int) val.shinyness 
     ); 
return 0; 
} 

O2 ile

GCC çıkışı: sabit olmayan bir argüman ile

main: 
    pushl %ebp 
    movl %esp, %ebp 
    andl $-16, %esp 
    subl $32, %esp 
    movl $1, 20(%esp) 
    movl $0, 16(%esp) 
    movl $1, 12(%esp) 
    movl $5, 8(%esp) 
    movl $.LC0, 4(%esp) 
    movl $1, (%esp) 
    call __printf_chk 
    xorl %eax, %eax 
    leave 
    ret 

: (uc = 0xa5 * random();):

main: 
    pushl %ebp 
    movl %esp, %ebp 
    andl $-16, %esp 
    subl $32, %esp 
    call random 
    movl $-91, %ecx 
    xorl %edx, %edx 
    movl $.LC0, 4(%esp) 
    movl $1, (%esp) 
    imull %ecx, %eax 
    movb %al, %dl 
    movl %edx, %eax 
    shrl $7, %eax 
    movl %eax, 20(%esp) 
    movl %edx, %eax 
    shrl $6, %eax 
    andl $1, %eax 
    movl %eax, 16(%esp) 
    movl %edx, %eax 
    andl $31, %edx 
    shrl $5, %eax 
    andl $1, %eax 
    movl %eax, 12(%esp) 
    movl %edx, 8(%esp) 
    call __printf_chk 
    xorl %eax, %eax 
    leave 
    ret 
İlgili konular