Могу ли я выделить определенное количество бит в C? - PullRequest
10 голосов
/ 12 ноября 2008

Я пытаюсь сохранить большое количество логической информации, которая определяется во время выполнения. Мне было интересно, каким может быть лучший метод.

В настоящее время я пытаюсь выделить память, используя:

pStatus = malloc((<number of data points>/8) + 1);

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

pStatus[element]

К сожалению, это, похоже, работает не очень хорошо. Во-первых, мне трудно инициализировать память целочисленным значением 0. Можно ли это сделать с помощью memset()? Тем не менее, я не думаю, что это влияет на причину сбоя при попытке доступа к pStatus[element].

Я также не совсем убежден, что этот подход является лучшим для использования. Что я действительно хочу, так это гигантская битовая маска, которая отражает статус логических значений. Я что-то пропустил?

Ответы [ 16 ]

0 голосов
/ 12 ноября 2008

Если вы не возражаете против написания оболочек, вы также можете использовать либо bit_set, либо bit_vector из C ++ STL, похоже, что они (особенно последние) имеют именно то, что вам нужно, уже закодированы, протестированы и упакованы (и множество навороты).

Очень жаль, что нам не хватает прямого способа использовать код C ++ в приложениях C (нет, создание обертки для меня не просто и не интересно, а значит требует больше работы в долгосрочной перспективе).

0 голосов
/ 12 ноября 2008

Логическое значение «никогда» не является отдельным значением в C. Так что структура может быть для того, чтобы вы начали.

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

Вот простой пример того, как вы могли бы сделать это с помощью структур и перечислений союзов

typedef unsigned char           BYTE;
typedef unsigned short          WORD;
typedef unsigned long int       DWORD;
typedef unsigned long long int  DDWORD;
enum STATUS
{
    status0 = 0x01,
    status1 = 0x02,
    status2 = 0x04,
    status3 = 0x08,
    status4 = 0x10,
    status5 = 0x20,
    status6 = 0x40,
    status7 = 0x80,
status_group = status0 + status1 +status4
};
#define GET_STATUS( S ) ( ((status.DDBuf&(DDWORD)S)==(DDWORD)S) ? 1 : 0  )
#define SET_STATUS( S ) (  (status.DDBuf|=  (DDWORD)S) )
#define CLR_STATUS( S ) (  (status.DDBuf&= ~(DDWORD)S) )
static union {
 BYTE   BBuf[8];
 WORD   WWBuf[4];
 DWORD  DWBuf[2];
 DDWORD DDBuf;
}status;

int main(void)
{
    // Reset status bits
    status.BBuf[0] = 0;
    printf( "%d \n", GET_STATUS( status0 ) );

    SET_STATUS( status0 );
    printf( "%d \n", GET_STATUS( status0 ) );

    CLR_STATUS(status0);
    printf( "%d \n", GET_STATUS( status0 ) );
    SET_STATUS( status_group );
    printf( "%d \n", GET_STATUS( status0 ) );
    system( "pause" );
    return 0;
}

Надеюсь, это поможет. Этот пример может обрабатывать до 64 логических значений состояния и может быть легко расширен.

Этот пример основан на Char = 8 битов int = 16 битов long int = 32 битов и long long int = 64 битов

Я также добавил поддержку групп состояний.

0 голосов
/ 12 ноября 2008

Код распределения правильный, см. Функции set_bit() и get_bit(), приведенные в этого ответа для доступа к логическому значению.

0 голосов
/ 12 ноября 2008

Вам нужно выделить c = malloc((N+7)/8) байтов, и вы можете установить nth с помощью

 c[n/8]=((c[n/8] & ~(0x80 >> (n%8))) | (0x80>>(n%8)));

очистить с

 c[n/8] &= ~(0x80 >> (n%8));

и тест с

 if(c[n/8] & (0x80 >> (n%8))) blah();
0 голосов
/ 12 ноября 2008
 pStatus = malloc((<number of data points>/8) + 1);

Эта часть в порядке.

 pStatus[element]

вот где у вас проблемы. Вы адресные байты, когда вы хотите адресовать биты.

 pStatus[element / 8 ]  

даст вам правильный байт в массиве.

0 голосов
/ 12 ноября 2008

pStatus [элемент] не обращается к биту. Точный байт, который он получает, зависит от типа pStatus - я предполагаю, что char * или эквивалентный - поэтому pStatus [element] возвращает вам байт элемента.

Вы можете установить memset на 0, да.

...