2016-09-22 7 views
0

일부 프레임 구조에서 작업하면서 이상한 행동을 보았습니다. 나는 빨리 다음과 같이 독립적 인 샘플 코드에서 테스트 :이상한 구조체 패킹

struct non_alligned_struct 
{ 
    uint8_t flag; 

    // start of uint32 bit fields 
    uint32_t a:2; 
    uint32_t b:2; 
    uint32_t c:1; 
    uint32_t d:1; 
    uint32_t e:1; 
    uint32_t f:1; 
    uint32_t g:3; 
    uint32_t h:1; 
    uint32_t i:1; 
    uint32_t j:3; 
    uint32_t k:3; 
    uint32_t l:1; 
    uint32_t m:1; 
    uint32_t n:1; 
    uint32_t o:1; 
    uint32_t p:3; 
    uint32_t q:2; 
    uint32_t r:1; 
    uint32_t s:1; 
    uint32_t t:2; 
    //4 bytes ends here 

    // shouldn't this start at 5th byte ?? 
    uint16_t u; 

    uint16_t v:13; 
    uint16_t w:3; 

    uint16_t x; 

    uint16_t y:13; 
    uint16_t z:3; 
}; 

int main() 
{ 
    struct non_alligned_struct obj1; 
    void *ptr1 = &obj1; 
    void *ptr2 = &(obj1.u); 
    printf("ptr1: %p, ptr2: %p, ptr2 - ptr1: %d\n", ptr1, ptr2, ptr2 - ptr1); 
    return 0; 
} 

출력 : PTR1 : 0x7fff3216a620, PTR2 : 0x7fff3216a626, PTR2 - PTR1 : 6

질문 : PTR2 왜 - PTR1 6이어야한다. 내 계산 당 5로해야합니다. 또한 구조 13 바이트, 그래서 4 바이트 정렬 및 패딩 이상한 방식으로 수행됩니다. I 멤버 변수에 임의의 값을 부여하여 검증 I 패딩은 다음 굵은 위치

00000000에서 행해진 관찰 : 01 22 31 10 67 00 FE FF 86 01 FE FF 86 01 00

+0

확실히 ptr2-ptr1은 6과 같습니다 ... – DigitalNinja

+0

MSVC에서'struct'를'#pragma pack (push, 1)'과'#pragma pack (pop)'으로 묶으면 예상 결과'5' 그렇지 않으면'8'입니다. void * 형에 대한 포인터 산술은 구현이 정의 되었기 때문에'void *'포인터를'char *'로 변경해야했습니다. –

+0

'void *'s에 대한 산술 연산을하는 제약 위반. 컴파일러가이 오류에 대한 진단을 내야했습니다. – EOF

답변

1

비트 필드의 정렬은 구현에 따라 정의됩니다. 귀하의 구현은 uint32_t 필드에 대해 1 바이트 또는 2 바이트 정렬을 사용하는 것 같습니다. 결과적으로 flag은 바이트 0을 차지하고 비트 필드는 바이트 1..4 또는 2..5를 차지합니다. 전자의 경우 u은 2 바이트 정렬로 기본 설정되어 바이트 6.7에 배치되고 후자의 경우 6..7이 이미 다음 사용 가능한 슬롯입니다.

+0

OP의 대담한 16 진수 덤프에서 비트 필드가 1 바이트 정렬되고'u' 필드가'uint16_t'에 대해 예상대로 2 바이트 정렬되었다고 말하고 싶습니다. – rodrigo

1

질문 : 왜 PTR2 - PTR1 사이 구조체 금액의 요소 및 배열들은 후 패딩을 삽입 할 5

C가 허용 구현 했어야 내 계산에 따라 6.이어야한다 고르다. 또한 비트 필드가 주소 지정 가능한 저장 장치에 할당되는 방법과 할당 할 수있는 주소 지정 가능한 저장 장치의 크기를 지정하지 않습니다. 특히, 선언 된 유형의 비트 필드는 표준에 관한 한 아무 것도 말하지 않습니다.

은 결국 따라서, 당신은 u 전에 구조체 멤버를 표현하기 위해 필요한 비트 수를 계산할 수 있습니다,하지만 당신은 u의 오프셋 (offset) 무엇을하지 컴퓨팅은 포함하는 구조의 선언에 기초해야 할 수 있습니다.

실제적으로 u이 구조의 시작 부분에서 균등 한 오프셋에 위치하는 것을 보는 것은 놀라운 일이 아닙니다. 구조체 표현에는 약간의 패딩이 있지만 비트 필드의 계산 주소를 사용할 수 없으므로 패딩이 정확한 위치를 정확히 알 수 없습니다.