2010-05-06 5 views
1

나는 내 코드에 다음 구조체 선언과 타입 정의를 가지고 :struct 크기가 typedef 버전과 다른가요?

struct blockHeaderStruct { 
    bool allocated; 
    unsigned int length; 
}; 
typedef struct blockHeaderStruct blockHeader; 

내가 sizeof(blockheader)을 할 때, 내가 다시 4 바이트의 값을 얻을,하지만 난 sizeof(struct blockHeaderStruct)을 수행 할 때, 나는 8 바이트를 얻을.

왜 이런 일이 발생합니까? 왜 나는 다시 5 점을 얻지 못하는가?

+5

'sizeof' 포인터를 사용하지 않으시겠습니까? – Potatoswatter

+1

또한 http : //en.wikipedia의 패딩 때문에.org/wiki/Data_alignment에서 예상 값은 5가 아니라 8입니다. – Potatoswatter

+0

어떤 플랫폼입니까? 어느 컴파일러인가? –

답변

3

구조체의 정의를 보면 1 바이트 값 뒤에 4 바이트 정수가옵니다. 이 정수는 컴파일러가 1 바이트 bool 다음에 3 바이트 패딩을 삽입하도록하는 4 바이트 경계에 할당되어야합니다. struct의 크기를 8 바이트로 만든다. 이를 방지하기 위해 구조체의 요소 순서를 변경할 수 있습니다.

다른 값을 반환하는 두 개의 sizeof 호출의 경우 여기에 오타가없고 포인터의 크기 또는 다른 유형 또는 일부 정수 변수를 사용하지 않는 것이 확실합니까?

+5

요소의 순서를 변경하면 경우에 따라 패딩이 줄어들지 만이 경우에는 그렇지 않습니다. – Potatoswatter

+0

"packed"컴파일러 플래그를 추가하여 항상 5 바이트를 반환 할 수도 있습니다. – Myles

-1

일부 컴파일러는 항상 2의 거듭 제곱으로 데이터를 할당하도록 최적화합니다 (4 개는 4 개이지만 5 개는 8 개로 반올림 됨).

+0

그래도 부울 값을 없애지 않겠습니까? – samoz

+0

일반적으로 변수는 개별 크기로 정렬됩니다. – Potatoswatter

+0

플랫폼에있는 각 데이터 유형의 크기를 알 수는 없지만, 5를 얻고 8을 얻었다면이 이유가 있습니다. – magicdanw

4

우선, sizeof(blockHeaderStruct)을 할 수 없습니다. 그것은 단순히 컴파일되지 않습니다. 당신이 할 수있는 일은 실제로 결과로 8 바이트를 줄 수있는 sizeof(struct blockHeaderStruct)입니다.

두 번째로 sizeof(blockheader)과 다른 결과를 얻는 것은 거의 없습니다. sizeof(blockHeaderStruct) (다시 컴파일하지도 않음)에 대한 언급으로 판단하면 문제에 대한 설명이 부정확합니다. 당신이 실제로하고있는 일을 자세히 살펴보십시오. 대부분 포인터 타입 (구조 타입이 아닌)을 가진 sizeof을 가지고 있습니다.

어쨌든 실제 코드를 게시 해보십시오.

+1

sizeof (blockHeaderStruct)는 g ++ 4.2에서 나에게 잘 컴파일되어있다. (이것은 C++이 아닌 C++ 태그이다.) –

+0

@ 마크 B : 이것은 원래 C 태그가 붙어 있었고, C++은 단 7 시간 만에 태그를 다시 붙였습니다. 내 대답은 18 시간 전에 게시되었습니다. – AnT

1

대부분의 시나리오는 32 비트 시스템에서 struct이 아닌 포인터의 크기를 실제로보고 있다는 것입니다. 그러나, int은 2 바이트 (16 비트) 일 수있다. 이 경우, 구조의 예상 크기는 4 : 2의 다음의 여러까지 bool

  • 라운드 대한 int
  • 1 바이트

    • 2 바이트, 구조체의 크기 때문에 보통 가장 큰 프리미티브 멤버의 크기의 배수로 반올림됩니다.

    비록 typedef이 주어지면 아무 것도 설명 할 수 없지만 sizeof(blockHeaderStruct) != sizeof(struct blockHeader)입니다. 그것은 완전히 불가능합니다.

  • 0

    실제로 내 소스 파일에서 바로 그 코드를 으로 복사했습니다.

    확인.나는를 sizeof (blockheader)을 수행 할 때

    , 나는 blockheader 어딘가에 형식 정의하고 그 유형은 4 바이트를 차지 또는 유형 4 바이트를 필요로 같은 4 바이트의 값이 다시

    것 같습니다 를 얻을 수 조정.

    sizeof (blockHeader)를 시도하면 유형이 표시됩니다.

    내가 sizeof (blockHeaderStruct) 할 때, 나는 8 바이트를 얻습니다.

    정렬 문제가있는 이유는 blockHeaders 배열이 필요한 경우 필요한 메모리 양을 계산할 수 있기 때문입니다. 또는 배열이 있고 복사 할 메모리 양을 계산해야 할 경우 계산할 수 있습니다.

    모든 구조체 멤버를 4 대신 또는 컴파일러의 기본값 대신 1의 배수가되는 주소에 정렬하려면 컴파일러에서 #pragma를 제공 할 수 있습니다. 그런 다음 메모리를 절약 할 수 있지만 정렬되지 않은 데이터에 액세스하려면 액세스 속도가 느려질 수 있습니다.

    +0

    이고 거의 모든 컴파일러에서 해당 pragma의 이름은'#pragma align'입니다. – Potatoswatter

    0

    구조체 할당은 일반적으로 4 바이트 경계에서 발생합니다. 즉, 컴파일러는 다음 데이터 형식으로 시작하기 전에 4 바이트 경계까지 구조체 내의 데이터 형식을 채 웁니다.

    sizeof(blockHeader) == 8 
    sizeof(struct blockHeader) == 8 
    sizeof(blockHeaderPtr) == 4 
    

    (참고 :이 C++의 것을 감안할 때

    struct blockHeaderStruct { 
         bool allocated;   // 1 byte followed by 3 pad bytes 
         unsigned int length; // 4 bytes 
        }; 
        typedef struct blockHeaderStruct blockHeader; 
        typedef struct blockHeaderStruct *blockHeaderPtr; 
    

    를 sizeof 작업이 될 것입니다 (부울 뭔가로 #define한다 할 필요)이 아닌 C (부울는 sizeof 연산자 1) 마지막 항목은 64 비트 컴파일러의 경우 8입니다.)

    처음 두 줄의 코드 사이에는 크기에 차이가 없어야합니다. typedef는 단순히 기존 유형에 별명을 지정합니다. 세 번째는 32 비트 머신에서 4 바이트이고 64 비트 머신에서 8 바이트 인 포인터 크기를 취하는 것입니다.


    이 문제를 해결하려면 구조체를 정의하기 전에 #pragma pack 지시어를 적용하면됩니다. 이렇게하면 컴파일러가 지정된 경계에 압축합니다. 일반적으로 1, 2 또는 4로 설정됩니다 (일반적으로 4가 기본값이며 설정하지 않아도 됨).

    #include <stddef.h> 
    #include <stdio.h> 
    
    #pragma pack(1) 
    struct blockHeaderStruct { 
        bool allocated; 
        unsigned int length; 
    }; 
    typedef struct blockHeaderStruct blockHeader; 
    
    int main() 
    { 
        printf("sizeof(blockHeader) == %li\n", sizeof(blockHeader)); 
        printf("sizeof(struct blockHeader) == %li\n", sizeof(struct blockHeaderStruct)); 
    
        return 0; 
    } 
    

    그램로 컴파일 ++ (우분투 4.4.1-4ubuntu9)에서 4.4.1

    결과 :

    sizeof(blockHeader) == 5 
    sizeof(structblockHeader) == 5 
    

    당신은 일반적으로이 지침이 필요하지 않습니다. 구조체를 효율적으로 팩하는 것을 잊지 마십시오. 더 작은 데이터 유형을 함께 그룹화하십시오. 구조체가 주로 사용되지 않는 공간이기 때문에 대체 바이트 < 4 바이트 데이터 유형과 4 바이트 데이터 유형을 사용하지 마십시오. 이로 인해 네트워크 관련 응용 프로그램에 불필요한 대역폭이 발생할 수 있습니다.