IT

제로 길이 비트 필드의 실용적인 사용

itgroup 2023. 9. 5. 20:09
반응형

제로 길이 비트 필드의 실용적인 사용

C에 대해서는 완전히 확신할 수 없지만, C++은 0 길이의 이름 없는 비트 필드를 허용합니다.예:

struct X
{
    int : 0;
};
  • 질문 1:이것의 실용적인 용도는 무엇이라고 생각할 수 있습니까?
  • 질문 2:실제 사용법은 무엇입니까? (있는 경우)?

얼음 범죄의 답변 후 예제 편집

편집: 네, 현재 답변 덕분에 이론적인 목적을 알게 되었습니다.하지만 그 질문들은 실용적인 용도에 관한 것이기 때문에 여전히 유효합니다 :)

제로 길이 비트 필드를 사용하면 컴파일러가 레이아웃에 대한 다른 컴파일러나 아키텍처의 개념(이진 파일 형식과 같은 교차 플랫폼 데이터 구조) 또는 비트 수준 표준의 요구 사항(네트워크 패킷 또는 명령어 코드)과 같은 외부 요구 사항에 맞게 구조를 레이아웃하도록 할 수 있습니다.

실제 사례는 NEXT가 xnu 커널을 Motorola 68000(m68k) 아키텍처에서 i386 아키텍처로 포팅한 경우입니다.NeXT는 커널의 작동하는 m68k 버전을 가지고 있었습니다.i386으로 포팅했을 때, i386의 정렬 요구 사항이 m68k와 다르다는 것을 알게 되었고, m68k 머신과 i386 머신은 NeXT 벤더별 BOOTP 구조의 레이아웃에 동의하지 않았습니다.i386 구조 레이아웃이 m68k와 일치하도록 하기 위해, 그들은 길이 0의 이름 없는 비트 필드를 추가하여 강제로NV1구조/nv_U유니온은 16비트 정렬됩니다.

다음은 Mac OS X 10.6.5 xnu 소스 코드의 관련 부분입니다.

/* from xnu/bsd/netinet/bootp.h */
/*
 * Bootstrap Protocol (BOOTP).  RFC 951.
 */
/*
 * HISTORY
 *
 * 14 May 1992 ? at NeXT
 *  Added correct padding to struct nextvend.  This is
 *  needed for the i386 due to alignment differences wrt
 *  the m68k.  Also adjusted the size of the array fields
 *  because the NeXT vendor area was overflowing the bootp
 *  packet.
 */
/* . . . */
struct nextvend {
  u_char nv_magic[4]; /* Magic number for vendor specificity */
  u_char nv_version;  /* NeXT protocol version */
  /*
   * Round the beginning
   * of the union to a 16
   * bit boundary due to
   * struct/union alignment
   * on the m68k.
   */
  unsigned short  :0;
  union {
    u_char NV0[58];
    struct {
      u_char NV1_opcode;  /* opcode - Version 1 */
      u_char NV1_xid; /* transcation id */
      u_char NV1_text[NVMAXTEXT]; /* text */
      u_char NV1_null;  /* null terminator */
    } NV1;
  } nv_U;
};

표준(9.6/2)은 특수한 경우 0 길이 비트 필드만 허용합니다.

특별한 경우로, 너비가 0인 명명되지 않은 비트 필드는 할당 단위 경계에서 다음 비트 필드의 정렬을 지정합니다.명명되지 않은 비트 필드를 선언하는 경우에만 상수 표현식이 0과 같은 값이 될 수 있습니다.

이 인용문에 유일한 용도가 설명되어 있습니다. 아직 실용적인 코드로 본 적이 없습니다.


참고로 저는 VS 2010에서 다음 코드를 시도했습니다.

struct X {
    int i : 3, j : 5;
};

struct Y {
    int i : 3, : 0, j : 5; // nice syntax huh ?
};

int main()
{
    std::cout << sizeof(X) << " - " << sizeof(Y) << std::endl;
}

내 기계의 출력은 실제로 다음과 같습니다.4 - 8.

struct X { int : 0; };

C에서 정의되지 않은 동작입니다.

(내 항목 강조)를 참조하십시오.

(C99, 6.7.2.1p2) "struct-or-union-specifier에 struct-declaration-list가 존재하면 번역 단위 내에서 새로운 유형이 선언됩니다.struct-declaration-list는 구조체 또는 유니언의 구성원에 대한 일련의 선언입니다.struct-declaration-list에 명명된 멤버가 없으면 동작이 정의되지 않습니다."

(C11의 문구는 동일합니다.)

없는 에 름이없비사수있다습니용할을 사용할 수.0너비이지만 구조물에 다른 명명된 멤버가 없는 경우에는 그렇지 않습니다.

예:

struct W { int a:1; int :0; };  // OK
struct X { int :0; };           // Undefined Behavior

그건 그렇고, 두 번째 선언문은gcc는 (C 에준의과요않음지구되다발해니)와 함께 Standard에서 하지 않음)을합니다.-pedantic.

반면에:

 struct X { int :0; };

, 를 들어 리눅스(GNU C에정있습다니의)에서 됩니다. 예를 들어 리눅스 커널()에 의해 사용됩니다.include/linux/bug.h조건이 참일 경우 다음 매크로를 사용하여 컴파일 오류를 강제로 적용합니다.

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))

이것은 MSDN에서 가져온 것이며 Microsoft Specific으로 표시되지 않았기 때문에 일반적인 C++ 표준입니다.

이름 없는 비트 필드 폭 0은 다음 비트 필드를 다음 유형 경계로 강제 정렬합니다. 여기서 type은 멤버의 유형입니다.

이제 C11 표준은 길이가 0인 비트 필드를 포함할 수 있습니다.여기 C 위원회 초안(N1570)의 예가 있는데, 이는 실용적인 사용법을 보여준다고 생각합니다.

메모리 .14 메모리 위치
...
: 으로 선언

struct {
  char a;
  int b:5, c:11, :0, d:8;
  struct { int ee:8; } e;
}

위치가 되어 있습니다. 그는버멤.a 비트 필드 및 트 드d그리고.e.ee는 각각 별개의 메모리 위치이며, 서로 간섭하지 않고 동시에 수정할 수 있습니다.비트 필드b그리고.c함께 네 번째 메모리 위치를 구성합니다. 필드:b그리고.c수정할 동에수수없습니다정할시다▁cannot없니습,▁but수▁conc▁modified▁be.b그리고.a예를 들어, 그럴 수 있습니다.

비트 필드 사이에 0 길이 비트 필드를 포함합니다.c그리고.d할 수 .b그리고.d뿐만 아니라.

언급URL : https://stackoverflow.com/questions/4297095/practical-use-of-zero-length-bitfields

반응형