2013-05-28 3 views
0

Я написал эту программу:Как манипулировать бит целочисленного типа в c?

#include <stdlib.h> 
#include <stdio.h> 
#include <stdbool.h> 

struct A { 
    bool a; 
    bool b; 
    bool c; 
    bool d; 
}; 

struct B { 
    int a; 
}; 

int main() { 
    struct A* pa = malloc(sizeof(struct A)); 
    struct B* pb = (struct B*) pa; 
    pa->a = 0; 
    pa->b = 1; 
    pa->c = 0; 
    pa->d = 0; 

    printf("value of pint is %i\n", pb->a); 
    return 0; 
} 

Я ожидаю, что печать 2 (0010), но выход 256. Любая одна тучи помощь, что не так с этим кодом?

+1

% Я напечатаю номер, вот почему – paulm

+5

bools - это не бит. Если вы хотите бит-поле, используйте бит-поле. – harold

ответ

2

После инициализации pa, у вас есть

*pa = { 0x00, 0x01, 0x00, 0x00 } 

, поскольку каждый BOOL является один байт. И когда вы набираете закинуть в целочисленное значение, вы получите (в Little Endian машины) *pb в

*pb = 0x00000100 

, который, очевидно, 256. Понял?

Если вы хотите, вы можете определить struct A как:

struct A { 
    bool a:1; 
    bool b:1; 
    bool c:1; 
    bool d:1; 
}; 

но не типаж указатель на struct A, что и struct B поскольку размеры обеих структур являются то разные.

Это может быть полезным для вас в будущем:

union A { 
    struct { 
    bool bit0:1; 
    bool bit1:1; 
    bool bit2:1; 
    bool bit3:1; 
    bool bit4:1; 
    bool bit5:1; 
    bool bit6:1; 
    bool bit7:1; 
    }; 
    unsigned char cByte; 
}; 

Определяя таким образом, вы можете получить доступ к этому, как побитовое или побайтно.

+0

Да, конечно, я нашел эту статью очень полезной http://betterexplained.com/articles/understanding-big-and-little-endian-byte-order/ –

+0

очень полезную информацию и введение союза usecase. –

0

Попробуйте

struct A { 
    bool a:1; 
    bool b:1; 
    bool c:1; 
    bool d:1; 
}; 

:1 часть силы компилятор Alloc 1 бит вместо 1 байт для каждой переменной-члена, поэтому расположение память STRUCT A будет выглядеть как этот (предположим, Little Endian):

|-byte 1-|-byte 2-|-byte 3-|-byte 3-| 
uuuudcba uuuuuuuu uuuuuuuu uuuuuuuu 

, где u пожертвования для неиспользованных. когда приведение его в целое, вы получите целое представление:

uuuuuuuu uuuuuuuu uuuuuuuu uuuudcba 

И из-за разные битные порядка различного реализации компилятора, вы можете получить также получить обратный результат 4 (0100) вместо 2 (0010)

+1

Заметили ли вы актерский состав позже? Можете ли вы добавить, что произойдет, когда это будет сделано? – UmNyobe

+0

Замечание: порядок битбитов полностью зависит от компилятора (от высокого к низкому или от низкого к высокому), а habe - ничего общего с контентом. – Vovanium

3

Я ожидаю, что он напечатает 2 (0010), но выход будет 256. Любое облако поможет, что что-то не так с этим кодом?

A bool занимает не менее одного байт. В вашем случае, по-видимому, ровно один байт, а ваша платформа немногочисленна (с 8-битным char). Таким образом, второй (наименее значащий) байт равен 1, все остальные байты 0 составляют 1*256.

Обратите внимание, что тип punning через pa и pb нарушает строгий псевдоним.

Используйте union для портативного типа каламбура.

1

%i печатает целое число.

BOOL является целым числом без знака типа достаточно велик, чтобы хранить значения 0 и 1.

Вы можете напечатать логическое значение таким образом:

printf("%d\n", b); 
1

Вы печатаете число в небольшой Endian нотации. Эффективно, что вы Печатаемая:

0 * 256^0 + 1 * 256^1 + 0 * 256^2 + 0 * 256^3 

Если вы решили использовать битовые поля (как это было предложено кем-то еще), вы должны использовать %x для печати в шестнадцатеричном формате. Если вы строго хотите печатать в двоичном формате, вам нужно будет сделать это, используя цикл, проходящий через отдельные биты.

Смежные вопросы