bestsource

비트 필드에 열거형을 사용해도 안전합니까?

bestsource 2023. 10. 21. 10:36
반응형

비트 필드에 열거형을 사용해도 안전합니까?

저는 다음과 같은 구조를 가지고 있습니다.

typedef struct my_struct{
    unsigned long       a;
    unsigned long       b;
    char*               c;
    unsigned int        d1  :1;
    unsigned int        d2  :4;
    unsigned int        d3  :4;
    unsigned int        d4  :23;
} my_type, *p_type;

필드d3현재 에 의해 정의됩니다.#defines 로부터 뻗는0x00까지0x0D.

정말로.d3는 열거입니다.그래서 교체하고 싶은 유혹이 있습니다.

    unsigned int        d3  :4;

타고

    my_enum             d3  :4;

이것은 안전한가요?

코드는 다양한 코드로 컴파일해야 합니다.

  • 컴파일러 (GCC, Visual Studio, 내장된 것)
  • 플랫폼(Win32, Linux, 내장된 것)
  • 구성(C로 컴파일, C++로 컴파일)

분명히, 나는 그의 정의를 남길 수 있을 것입니다.d3그대로 그리고 내 코드에 있는 열거를 사용하고, 그것을 할당합니다.d3C++에서는 안 될 겁니다.

표준을 지원하는 모든 C++ 컴파일러에서 허용됩니다.

C++03 표준 9.6/3

비트 필드는 적분 또는 열거형(3.9.1)을 가져야 합니다.일반 문자(명시적으로 서명된 문자 또는 서명되지 않은 문자), 짧은 비트 필드, 짧은 비트 필드 또는 긴 비트 필드 중 어느 것이 서명된 것인지 또는 서명되지 않은 것인지에 대해 구현이 정의됩니다.

C++03 표준 9.6/4

열거형의 값이 동일한 열거형의 비트 필드에 저장되어 있고 해당 열거형의 모든 값을 담을 수 있을 정도로 비트 필드의 비트 수가 클 경우 원래 열거형의 값과 비트 필드의 값은 동일하게 비교됩니다.

enum BOOL { f=0, t=1 };

struct A {
    BOOL b:1;
};

void f() {
    A a;
    a.b = t;
    a.b == t // shall yield true
}

그러나 열거형에 서명되지 않은 기본 형식이 있다고 간주할 수는 없습니다.

C++03 표준 7.2/5

열거형의 기본 형식은 열거형에 정의된 모든 열거형 값을 나타낼 수 있는 통합 형식입니다.열거형의 값이 int 또는 unsigned int에 들어갈 수 없는 경우를 제외하고 어떤 적분 유형이 열거형의 기본 유형으로 사용되는지 구현 정의되어 있습니다.

C와 C++는 답변이 다를 것입니다.

In C 비트 필드는 다음으로 제한됩니다.signed int,unsigned int,_Bool그리고.int이런 맥락에서는 처음 두 가지 중 하나가 될 수 있습니다.컴파일러 구현자는 원하는 대로 해당 목록에 추가할 수 있지만 지원하는 유형을 문서화해야 합니다.

그래서 당신의 질문에 답하기 위해, 당신이 당신의 코드가 모든 C 컴파일러들에게 휴대 가능한지를 확실히 하기를 원한다면, 아니요, 를 사용합니다.enumtype은 옵션이 아닙니다.

현재 표준의 해당 단락은 다음과 같습니다.

비트 필드에는 _Boool, signed int, unsigned int 또는 기타 구현 정의된 유형의 정규 또는 비정규 버전이 있어야 합니다.원자 유형이 허용되는지 여부는 구현에 정의되어 있습니다.

아니요.

비트 필드는 컴파일러마다 상당히 다르게 구현됩니다.비트 필드를 0과 1의 두 값으로 정의하고 열거형 비트 필드를 사용하려고 하면 다음과 같은 문제가 발생할 수 있습니다.

비트 필드는 gcc 및 clang으로 서명되지 않고 VC++로 서명됩니다.즉, 0과 1을 저장하려면 2비트 비트 필드(1비트 부호 비트 필드는 0과 음의 비트 필드만 저장할 수 있음)가 필요합니다.

그럼 짐 싸는 것도 걱정해야겠네요.VC++는 크기가 일치하는 경우 인접 비트 필드만 동일한 백업 저장소로 패킹합니다.gcc와 clang에 대한 규칙이 무엇인지 잘 모르겠지만 VC++의 경우 비트 필드에 대한 기본 백업 저장소는 int입니다.따라서, 예를 들어, bool과 enum의 혼합인 일련의 비트 필드는 VC++로 매우 불량하게 포장됩니다.

C++ 11 유형의 열거형으로 이 문제를 해결할 수 있습니다.

enum Foo: 부호 없는 문자 {1, 2};

그러나 1비트 비트 필드에서 이를 사용하면 gcc가 불만을 제기합니다.

경고: '비트필드테스트::g'가 너무 작아서 [기본적으로 활성화]의 모든 값을 유지할 수 없습니다.

승리는 없는 것 같습니다.

C에서는 정의되지 않은 동작입니다. 비트 필드는 다음을 가질 수 있기 때문입니다.signed int,int아니면unsigned int유형(또는_BoolC99)와 함께.

6.5.2.1 :

비트 필드에는 int, unsigned int 또는 signed int 중 하나의 정규 버전 또는 비정규 버전의 형식이 있어야 합니다.(아마도 자격이 있는) int 비트 필드의 고차 비트 위치가 부호 비트로 취급되는지 여부는 구현 정의됩니다.비트 필드는 지정된 비트 수로 구성된 적분 유형으로 해석됩니다.

그렇지 않은 경우 일부 컴파일러는 오늘날 이를 확장(표준에서 확장자의 구현 정의 동작)으로 받아들입니다.

언급URL : https://stackoverflow.com/questions/11983231/is-it-safe-to-use-an-enum-in-a-bit-field

반응형