문제

런타임 시 결정되는 많은 양의 불리언 정보를 저장하려고 합니다.가장 좋은 방법이 무엇인지 궁금합니다.

현재 다음을 사용하여 메모리를 할당하려고 시도했습니다.

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

이것이 나에게 작업하기에 충분한 비트를 제공할 것이라고 생각합니다.그런 다음 배열 표기법의 포인터를 사용하여 각 부울 값을 참조할 수 있습니다.

pStatus[element]

불행히도 이것은 잘 작동하지 않는 것 같습니다.첫째, 메모리를 정수 값으로 초기화하는 데 어려움이 있습니다. 0.다음을 사용하여 이 작업을 수행할 수 있습니까? memset()?그래도 액세스하려고 할 때 충돌이 발생하는 이유에는 이것이 영향을 미치지 않는다고 생각합니다. pStatus[element].

나는 또한 이 접근법이 사용하기에 가장 좋은 접근법이라고 완전히 확신하지 못합니다.내가 정말로 원하는 것은 본질적으로 부울 값의 상태를 반영하는 거대한 비트마스크입니다.내가 뭔가를 놓친 걸까요?

도움이 되었습니까?

해결책

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

이것은 비트에 충분한 바이트를 할당합니다. 하지만,

pStatus[element]

이것은 요소에 액세스합니다 바이트, 비트가 아닙니다. 따라서 요소가 총 비트 수의 8 분의 1 이상이면 배분 된 배열의 끝에 액세스 할 수 있습니다.

몇 가지 도우미 기능을 정의합니다

int get_bit(int element)
{
    uint byte_index = element/8;
    uint bit_index = element % 8;
    uint bit_mask = ( 1 << bit_index);

    return ((pStatus[byte_index] & bit_mask) != 0);
}

void set_bit (int element)
{
    uint byte_index = element/8;
    uint bit_index = element % 8;
    uint bit_mask = ( 1 << bit_index);

    pStatus[byte_index] |= bit_mask);
}

void clear_bit (int element)
{
    uint byte_index = element/8;
    uint bit_index = element % 8;
    uint bit_mask = ( 1 << bit_index);

    pStatus[byte_index] &= ~bit_mask;
}

(명확성을 위해 외식하는 요소 범위에 대한 오류 확인.이 매크로도 만들 수도 있습니다)

다른 팁

... 이것이 나에게 충분한 비트를 줄 것이라고 생각합니다. 그런 다음 배열 표기법의 포인터를 사용하여 각 부울 값을 참조 할 수 있습니다.

pStatus[element]

요소가 해결 중입니다 바이트, 비트가 아닙니다. 당신은 다음과 같은 것을 원합니다 :

pStatus[element/8] & (1 << (element % 8))

작은 포인트 : N 비트를 저장하기에 충분한 메모리를 얻으려면 (N/8) + 1 바이트는 부정확합니다 (너무 많을 수 있음).

(n+7)/8은 항상 최소 수입니다.

글쎄, 가장 간단한 대답은 Malloc 대신 Calloc을 사용하는 것입니다.

그것은 메모리를 0으로 할당하는 메모리를 초기화하도록 정의되며 종종 페이지 매핑 트릭을 사용하여 수행 할 수 있습니다.

메모리 초기화 문제를 처리합니다. 여기서 다른 12 개의 게시물은 인덱싱 문제와 때때로 여분의 바이트 (오 공포!)를 할당한다는 사실을 적절히 해결하는 것 같습니다.

Pstatus [요소]는 해당 주소에서 전체 바이트를 제공합니다.

특정 요소를 설정하려면 다음과 같은 작업을 수행합니다.

pStatus[element >> 3] |= 1 << (element & 7);

요소를 재설정하려면 :

pStatus[element >> 3] &= ~1 << (element & 7);

그리고 요소를 테스트하려면 :

if (pStatus[element >> 3] & (1 << (element & 7)) != 0)

초기 할당이 있어야합니다

pstatus = malloc((<number of data points> + 7) / 8)

당신이 가진 것은 효과가 있지만 때때로 바이트를 낭비합니다.

여기서 C의 모든 응답은 바이트가 8비트라고 가정하는 것 같습니다.이는 C에서는 반드시 그렇지는 않습니다(물론 대부분의 주류 하드웨어에서는 해당되지만). 따라서 코드에서 이러한 가정을 하는 것은 다소 나쁜 형식입니다.

아키텍처 중립적인 코드를 작성하는 올바른 방법은 다음과 같습니다.

#include <limits.h>

그런 다음 CHAR_BIT 매크로가 필요할 때마다 "비트 수 char".

자신을 더 행복하게 만들고 해당 유형에서 작동 할 유형과 기능을 정의하십시오. 이렇게하면 비트 액세스가 너무 느리다는 것을 알면 부울 당 메모리 단위를 바이트/워드/롱으로 변경하거나 메모리가 실제로 문제 인 경우 스파 스/동적 데이터 구조를 채택 할 수 있습니다 (예 : 세트가 대부분 세트 인 경우. , 당신은 단지 1의 좌표로 목록을 유지할 수 있습니다.

비트 벡터의 구현 변경에 완전히 면역되도록 코드를 작성할 수 있습니다.

pstatus [요소]는 비트를 다루지 않습니다. 정확한 바이트는 pstatus의 유형에 따라 달라집니다 - 나는 char* 또는 동등한 것으로 가정하므로 pstatus [요소]는 요소 바이트를 얻습니다.

0으로 설정할 수 있습니다.

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

그 부분은 괜찮습니다.

 pStatus[element]

여기에 문제가있는 곳이 있습니다. 비트를 해결하려면 주소 바이트입니다.

 pStatus[element / 8 ]  

배열에서 올바른 바이트를 얻을 수 있습니다.

할당해야합니다 c = malloc((N+7)/8) 바이트, 당신은 n을 설정할 수 있습니다

 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();

랩퍼를 쓰지 않아도 C ++의 STL에서 Bit_set 또는 Bit_vector를 사용할 수도 있습니다. (특히 후자)는 정확히 필요한 것, 이미 코딩, 테스트 및 포장 된 것 같습니다 (및 많은 종과 휘파람 ).

C 응용 프로그램에서 C ++ 코드를 사용하는 간단한 방법이 부족한 것은 정말 부끄러운 일입니다 (아니요, 래퍼를 만드는 것은 나에게 간단하지 않으며 장기적으로 더 많은 작업을 의미합니다).

무엇이 잘못되었는지 std::vector<bool>?

여기에 하나의 대답만이 char_bit을 언급한다는 것이 놀랍습니다. 바이트는 종종 8 비트이지만 항상 그런 것은 아닙니다.

할당 코드가 정확합니다 set_bit() 그리고 get_bit() 주어진 기능 이 답변 부울에 접근합니다.

Eaanon01 솔루션 대신 몇 비트로 제한되어 있다면 B 비트 필드의 C 내장 시설을 사용하십시오 (사용할 수있는 경우는 거의 없지만 이것은 하나 일 것입니다).

이 비트 뱅킹 물건에 대해 추천 할 수 있습니다 : Herny Warrens "Hacker Delight"

부울은 C에서 별도의 값이 "절대" 없습니다.그래서 구조체가 당신을 움직이게 할 수도 있습니다.

mem 영역을 초기화하지 않기 때문에 개별적으로 초기화해야 하는 것은 사실입니다.

다음은 공용 구조체 및 열거형을 사용하여 이를 수행할 수 있는 방법에 대한 간단한 예입니다.

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비트를 기반으로 합니다.

이제 상태 그룹에 대한 지원도 추가되었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top