2010-08-12 2 views
0
typedef struct BaseMessage 
{ 
    int u32DeviceID : 32; 
    int u32CoreID : 32; 
    unsigned int u16Class : 16; 
    unsigned int u8OpCode : 8; 
    unsigned int u16CRC : 16; 
} BaseMessage; 

typedef struct MessageWithParameters 
{ 
     BaseMessage base; 
     int u8Param1 : 8; 
     int u8Param2 : 8; 
} MessageWithParameters; 

typedef struct FullMessage 
{ 
     int u32DeviceID : 32; 
     int u32CoreID : 32; 
     unsigned int u16Class : 16; 
     unsigned int u8OpCode : 8; 
     unsigned int u16CRC : 16; 
     int u8Param1 : 8; 
     int u8Param2 : 8; 
} FullMessage; 

int main() 
{ 
     printf("%d", sizeof(MessageWithParameters)); 
     printf("%d", sizeof(FullMessage)); 
} 

MessageWithParametersBaseMessage은 자체 크기가 어느 정도입니까?
스택에 있더라도?
나는 컴파일러가 MessageWithParametersFullMessage과 같은 형태로 변환한다고 추측하고있다.
맞습니까?두 구조체의 크기는 동일하지만 구조체 인스턴스가 하나만 포함되어 있습니다.

+0

구조체의 크기가 서로 다를 것으로 예상되는 이유는 무엇입니까? 왜 구조체의 크기가 다른지 묻는 이유는 무엇입니까? – nos

+0

BaseMessage base는 자체적으로 크기를 가져야하기 때문에. MessageWithParameters에 BaseMessage가 포함되어 있기 때문에 MessageWithParameters가 FullMessage보다 더 많은 크기를 차지할 것으로 예상했습니다. –

+0

내 컴퓨터에서 작동합니다. FullMessage와 MessageWithParameters 사이에는 아무런 관련이 없기 때문에 왜 동일하거나 다른 크기를 가져야한다고 생각하는지에 대한 질문을 던집니다. – nos

답변

1

다른 사람들은 구조체에 패딩이 발생한다고 말했기 때문입니다. C 언어 그 자체로 아무 것도 효과적으로 이것을 막을 수는 없습니다. 귀하의 컴파일러는 팩을 확장 할 수 있습니다 (예 : gcc가 attribute으로 구현 함). 팩 그러나 일을 실제로 처리하려면 필드를 오름차순 또는 내림차순으로 재정렬해야 정렬 틈이 가능한 작아집니다.

또한 이러한 구조에 비트 필드를 사용하는 것은 일반적으로 좋지 않습니다. 당신이 그 다음에 같은 C99 고정 된 크기의 정수 유형을 사용하는 경우 :이 경우

typedef struct BaseMessage 
{ 
    int32_t u32DeviceID; 
    int32_t u32CoreID; 
    uint16_t u16Class; 
    uint16_t u16CRC; 
    uint8_t u8OpCode; 
} BaseMessage; 

16 비트 (드문 요즘)에 컴파일러 alignes는 8 다른 추가의 단지 쓰레기와 함께 멀리 얻을 수 있다면 BaseMessage에 대한 비트.

+0

그리고 모든 것에 __attribute __ ((packed))하면 어떻게 될까요? –

+1

이것은 실제로 대상 플랫폼의 정렬 요구 사항에 따라 다릅니다. 필드를 재정렬하고'attribute'를 주면 이러한 요구 사항을 완화 할 수 있습니다. 하지만 실제로 존재하는 플랫폼의 결과는 많은 제약 조건에 달려 있습니다. 특히 CPU를 처리 할 수있는 영역은 무엇입니까?어쨌든 8 비트 경계에서의 정렬은 여전히 ​​존재한다고 생각하지 않기 때문에 대부분의 경우 끝에 갭이 생깁니다. –

+0

나는 구조체가 이더넷상에서 transfared되기 때문에 가능한 한 적은 메모리를 소비하는 것을 선호한다. 내 임베디드 장치와 내 서버 PC가 구조체에서 동일한 정렬을 유지하도록하려면 어떻게해야합니까? –

2

일부 패딩 문제가 있습니다. 기본에는 24 비트 "left over"가 있으며,이 비트에 매개 변수 struct에 16 비트가 추가됩니다. 왜 비트 필드를 사용하고 있습니까? 그들은 보편적으로 나쁜 생각으로 비난받습니다.

+0

나쁜 아이디어? 아니. 후방? 예. "항상해야한다"또는 "하지 마라."는 없습니다. 그러나 위와 같은 방법으로 사용하는 것은 좋지 않습니다. – adf88

+0

비트 필드에 어떤 문제가 있습니까? – Puppy

+0

임베디드 시스템 유형을 모방하는 데 사용하고 있습니다. 예를 들어 Xuint32, Xuint16, Xuint8. @ ad88 : 왜 나쁜 생각입니까? –

1

컴파일러에서 MessageWithParametersFullMessage처럼 보이는 것으로 추측됩니다.
맞습니까?

아무도 말할 수 없습니다. 컴파일러는 자유롭게 결정할 수 있습니다. 표준은 첫 번째 멤버 (파생 된 멤버 포함) 앞에 멤버 주문 및 패딩 금지를 보장합니다.

관련 문제