IT story

왜이 구조체 크기가 2가 아닌 3입니까?

hot-time 2020. 9. 2. 20:49
반응형

왜이 구조체 크기가 2가 아닌 3입니까?


이 구조체를 정의했습니다.

typedef struct
{
    char A:3;
    char B:3;
    char C:3;
    char D:3;
    char E:3;
} col; 

sizeof(col)나에게 (3)의 출력을 제공하지만 2이어야한다? 한 요소 만 언급하면 sizeof2가됩니다. 이유를 이해할 수 없습니다. 3 비트의 5 개 요소가 15 비트와 같고 2 바이트 미만입니다.

이와 같은 구조를 정의 할 때 "내부 크기"가 있습니까? 지금까지의 언어 개념에서 3이 아닌 2 바이트 크기를 예상했기 때문에 설명이 필요합니다.


char필드의 기본 유형 으로 사용 하고 있기 때문에 컴파일러는 비트를 바이트 단위로 그룹화하려고 시도하고 각 바이트에 8 비트 이상을 넣을 수 없으므로 바이트 당 2 개의 필드 만 저장할 수 있습니다.

구조체에서 사용하는 총 비트 합계는 15이므로 많은 데이터에 맞는 이상적인 크기는 short.

#include <stdio.h>

typedef struct
{
  char A:3;
  char B:3;
  char C:3;
  char D:3;
  char E:3;
} col; 


typedef struct {
  short A:3;
  short B:3;
  short C:3;
  short D:3;
  short E:3;
} col2; 


int main(){

  printf("size of col: %lu\n", sizeof(col));
  printf("size of col2: %lu\n", sizeof(col2));

}

위의 코드 (나와 같은 64 비트 플랫폼의 경우)는 실제로 2두 번째 구조체에 대해 양보 할 것 입니다. a보다 큰 경우 short구조체는 사용 된 유형의 요소를 하나만 채울 것이므로 동일한 플랫폼의 경우 구조체는 크기가 4 , 등이 int8이됩니다 long.


최소 정렬 경계 (1 바이트)에 걸쳐있는 비트 패킷 필드를 가질 수 없으므로 아마도 다음과 같이 압축 될 것입니다.

byte 1
  A : 3
  B : 3
  padding : 2
byte 2
  C : 3
  D : 3
  padding : 2
byte 3
  E : 3
  padding : 5

(동일한 바이트 내의 필드 / 패딩 순서는 의도적이지 않습니다. 컴파일러가 선호하는 방식을 배치 할 수 있으므로 아이디어를 제공하기위한 것입니다.)


처음 두 비트 필드는 단일 char. 세 번째는 그것에 맞지 않고 char새로운 것이 필요합니다. 3 + 3 + 3 = 9는 8 비트 문자에 맞지 않습니다.

So the first pair takes a char, the second pair takes a char, and the last bit field get a third char.


Most compilers allow you to control the padding, e.g. using #pragmas. Here's an example with GCC 4.8.1:

#include <stdio.h>

typedef struct
{
    char A:3;
    char B:3;
    char C:3;
    char D:3;
    char E:3;
} col;

#pragma pack(push, 1)
typedef struct {
    char A:3;
    char B:3;
    char C:3;
    char D:3;
    char E:3;
} col2;
#pragma pack(pop)

int main(){
    printf("size of col: %lu\n", sizeof(col));  // 3
    printf("size of col2: %lu\n", sizeof(col2));  // 2
}

Note that the default behaviour of the compiler is there for a reason and will probably give you better performance.


Even though the ANSI C standard specifies too little about how bitfields are packed to offer any significant advantage over "compilers are allowed to pack bitfields however they see fit", it nonetheless in many cases forbids compilers from packing things in the most efficient fashion.

In particular, if a structure contains bitfields, a compiler is required to store it as a structure which contains one or more anonymous fields of some "normal" storage type and then logically subdivide each such field into its constituent bitfield parts. Thus, given:

unsigned char foo1: 3;
unsigned char foo2: 3;
unsigned char foo3: 3;
unsigned char foo4: 3;
unsigned char foo5: 3;
unsigned char foo6: 3;
unsigned char foo7: 3;

If unsigned char is 8 bits, the compiler would be required to allocate four fields of that type, and assign two bitfields to all but one (which would be in a char field of its own). If all char declarations had been replaced with short, then there would be two fields of type short, one of which would hold five bitfields and the other of which would hold the remaining two.

On a processor without alignment restrictions, the data could be laid out more efficiently by using unsigned short for the first five fields and unsigned char for the last two, storing seven three-bit fields in three bytes. While it should be possible to store eight three-bit fields in three bytes, a compiler could only allow that if there existed a three-byte numeric type which could be used as the "outer field" type.

Personally, I consider bitfields as defined to be basically useless. If code needs to work with binary-packed data, it should explicitly define storage locations of actual types, and then use macros or some other such means to access the bits thereof. It would be helpful if C supported a syntax like:

unsigned short f1;
unsigned char f2;
union foo1 = f1:0.3;
union foo2 = f1:3.3;
union foo3 = f1:6.3;
union foo4 = f1:9.3;
union foo5 = f1:12.3;
union foo6 = f2:0.3;
union foo7 = f2:3.3;

Such a syntax, if allowed, would make it possible for code to use bitfields in a portable fashion, without regard for word sizes or byte orderings (foo0 would be in the three least-significant bits of f1, but those could be stored at the lower or higher address). Absent such a feature, however, macros are probably the only portable way to operate with such things.

참고URL : https://stackoverflow.com/questions/26699985/why-is-this-struct-size-3-instead-of-2

반응형