문제

방금 비트 필드로 테스트를했는데 결과는 놀랍습니다.

class test1 {
public:
    bool test_a:1;
    bool test_b:1;
    bool test_c:1;
    bool test_d:1;
    bool test_e:1;
    bool test_f:1;
    bool test_g:1;
    bool test_h:1;
};

class test2 {
public:
    int test_a:1;
    int test_b:1;
    int test_c:1;
    int test_d:1;
    int test_e:1;
    int test_f:1;
    int test_g:1;
    int test_h:1;
};

class test3 {
public:
    int test_a:1;
    bool test_b:1;
    int test_c:1;
    bool test_d:1;
    int test_e:1;
    bool test_f:1;
    int test_g:1;
    bool test_h:1;
};

결과는 다음과 같습니다.-

sizeof(test1) = 1   // This is what I'd expect. 8 bits in a byte
sizeof(test2) = 4   // Reasonable. Maybe padded out to the size of an int.
sizeof(test3) = 16  // What???

이것이 당신이 기대하는 것입니까, 아니면 컴파일러 버그입니까? (CodeGear C ++ Builder 2007, BTW ...)

도움이 되었습니까?

해결책

컴파일러는 정수 크기 경계에 대한 Test3의 모든 멤버를 정렬했습니다. 주어진 유형 (정수 비트 필드 또는 부울 비트 필드)에 블록이 사용되면 컴파일러는 다음 경계까지 다른 유형의 비트 필드를 더 할당하지 않습니다.

나는 그것이 버그인지 의심 스럽다. 아마도 시스템의 기본 아키텍처와 관련이있을 것입니다.

편집하다:

C ++ 컴파일러는 다음과 같이 메모리에 비트 필드를 할당합니다. 여러 연속 비트 필드 멤버 같은 유형의 순차적으로 할당됩니다. 새 유형을 할당해야하자마자 다음 논리 메모리 블록의 시작과 정렬됩니다. 다음 논리 블록은 프로세서에 따라 다릅니다. 일부 프로세서는 8 비트 경계에 맞게 정렬 할 수있는 반면, 다른 프로세서는 16 비트 경계에만 정렬 할 수 있습니다.

Test3에서 각 멤버는 이전 구성원과 다른 유형이므로 메모리 할당은 8 * (시스템의 최소 논리 블록 크기)입니다. 귀하의 경우, 최소 블록 크기는 2 바이트 (16 비트)이므로 TEST3의 크기는 8*2 = 16입니다.

8 비트 블록을 할당 할 수있는 시스템에서는 크기가 8이 될 것으로 예상됩니다.

다른 팁

많은 동작이 구현 (컴파일러)이 정의되므로 비트 필드에주의하십시오.

C ++ 03, 9.6 비트 필드 (pg. 163) :

클래스 객체 내에서 비트 필드 할당은 구현 정의됩니다. 비트 필드의 정렬은 구현 정의됩니다. 비트 필드는 일부 주소 가능한 할당 장치로 포장됩니다. [참고 : 비트 필드는 일부 기계가 아닌 일부 기계에 할당 장치를 가로 지릅니다. 비트 필드는 일부 기계에 오른쪽에서 왼쪽으로 할당되며 다른 기계에서 왼쪽에서 오른쪽으로 할당됩니다. ]

즉, 컴파일러의 버그가 아니라 어떻게 행동 해야하는지에 대한 표준 정의가 부족합니다.

와우, 놀랍습니다. GCC 4.2.4에서 결과는 각각 C 및 C ++ 모드 모두에서 1, 4 및 4입니다. C99와 C ++에서 작동하는 테스트 프로그램은 다음과 같습니다.

#ifndef __cplusplus
#include <stdbool.h>
#endif
#include <stdio.h>

struct test1 {
    bool test_a:1;
    bool test_b:1;
    bool test_c:1;
    bool test_d:1;
    bool test_e:1;
    bool test_f:1;
    bool test_g:1;
    bool test_h:1;
};

struct test2 {
    int test_a:1;
    int test_b:1;
    int test_c:1;
    int test_d:1;
    int test_e:1;
    int test_f:1;
    int test_g:1;
    int test_h:1;
};

struct test3 {
    int test_a:1;
    bool test_b:1;
    int test_c:1;
    bool test_d:1;
    int test_e:1;
    bool test_f:1;
    int test_g:1;
    bool test_h:1;
};

int
main()
{
    printf("%zu %zu %zu\n", sizeof (struct test1), sizeof (struct test2),
                            sizeof (struct test3));
    return 0;
}

일반적인 관찰로 서명했습니다 int 1 비트의 의미는 의미가 없습니다. 물론, 당신은 아마도 0을 저장하는 방법을 알아낼 수 있지만 문제는 시작됩니다.

하나의 비트는 2의 보완에서도 사인 비트이어야하지만 비트가 하나만 가지고 있어야합니다. 따라서이를 사인 비트로 할당하면 실제 값에 대한 비트가 없습니다. Steve Jessop이 두 사람의 보완을 사용하는 경우 -1을 나타내는 경우가 지적한 것처럼 사실이지만 여전히 0과 -1을 나타낼 수있는 "정수"데이터 유형은 다소 이상한 일이라고 생각합니다.

나 에게이 데이터 유형은 아무도 없다 (또는 Steve의 의견이 주어지면 작은) 감각.

사용 unsigned int small : 1; 서명되지 않도록하기 위해 값 0과 1을 모호하지 않은 방식으로 저장할 수 있습니다.

#include <iostream>
using namespace std;

bool ary_bool4[10];

struct MyStruct {
    bool a1 :1;
    bool a2 :1;
    bool a3 :1;
    bool a4 :1;
    char b1 :2;
    char b2 :2;
    char b3 :2;
    char b4 :6;
    char c1;
};

int main() {
    cout << "char size:\t" << sizeof(char) << endl;
    cout << "short int size:\t" << sizeof(short int) << endl;
    cout << "default int size:\t" << sizeof(int) << endl;
    cout << "long int size:\t" << sizeof(long int) << endl;
    cout << "long long int size:\t" << sizeof(long long int) << endl;
    cout << "ary_bool4 size:\t" << sizeof(ary_bool4) << endl;
    cout << "MyStruct size:\t" << sizeof(MyStruct) << endl;
    // cout << "long long long int size:\t" << sizeof(long long long int) << endl;
    return 0;
}

char size: 1
short int size: 2
default int size: 4
long int size: 4
long long int size: 8
ary_bool4 size: 10
MyStruct size: 3

"Samuel P. Harbison, Guy L. Steele] CA 참조":

문제 :

"컴파일러는 비트 필드의 최대 크기에 제약 조건을 자유롭게 부과하고 비트 필드가 교차 할 수없는 특정 주소 지정 경계를 지정합니다."

표준 내에서 수행 할 수있는 조작 :

"이름없는 비트 필드는 패딩을 제공하기 위해 구조에 포함될 수 있습니다."

"이름이없는 비트 필드에 0의 길이를 지정하면 특별한 의미가 있습니다. 이는 이전 비트 필드의 영역에 더 이상 비트 필드를 포장해서는 안된다는 것을 나타냅니다.

이것이 당신이 기대하는 것입니까, 아니면 컴파일러 버그입니까?

따라서 C89, C89는 수정 I, C99- 버그가 아닙니다. C ++에 대해 나는 모르겠지만 행동이 비슷하다고 생각합니다.

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