2010-07-16 5 views
1

구조체의 멤버가 C/C++로 패키지되어 있습니까? (팩킹 된 것은 그들이 컴팩트하고 필드 사이에 메모리 공간이 없다는 것을 의미합니다)C/C++에서 구조체의 필드 정렬

+7

'컴파일러 오류 : '정렬'하고 구조체를 작성하는 경우 '는 members'.'이 – kennytm

답변

9

이것은 정렬되지 않았거나 특정 정렬이나 패킹이 보장되지 않음을 의미합니다. 요소는 순서대로 있지만 컴파일러는 선택하는 곳에 패딩을 삽입 할 수 있습니다. 실제로는 (유용한) 정렬을 만듭니다. 예를 들어, x86 용 :

struct s 
{ 
    char c; 
    int i; 
}; 

아마 (그러나 반드시) C와 나는 사이 3 바이트가있을 것입니다. 이렇게하면 단어 경계에 i을 정렬 할 수있어 훨씬 빠른 메모리 액세스를 제공 할 수 있습니다 (일부 아키텍처에서는 필요). C99의 §6.7.2.1에서

:

Each non-bit-field member of a structure or union object is aligned in an implementation- defined manner appropriate to its type.

+1

이뿐만 아니라 치료를 필요로 사이에 명사를 기대 바이너리 파일에 저장하고 4 바이트 덩어리로 다시 읽습니다. 4 바이트 경계를 유지해야합니다. 그렇지 않으면 데이터가 올바르게 정렬되지 않기 때문에 이진 파일 관계로 구조체가 손실됩니다. –

+1

필자는 (다른 곳에서 정의 된 특정 형식의) 파일에서 이진 데이터를 읽는 코드를 작성하고 @ 0A0D가 설명하는 문제를 정확히 처리했습니다. [#pragma pack (push)'(그 전에)과'#pragma pack (pop)'(구조체 뒤에)을 사용하여 [#pragma pack (1) 이 섹션] (http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86). – lindes

2

을 일반적으로 없습니다. 일부 정보는 here입니다.

컴파일러에 따라, 당신은 (위의 링크에서) 도움이 프라그 마를 도입 할 수 있습니다 :

#pragma pack(push) /* push current alignment to stack */ 
#pragma pack(1)  /* set alignment to 1 byte boundary */ 

struct MyPackedData 
{ 
    char Data1; 
    long Data2; 
    char Data3; 
}; 

#pragma pack(pop) /* restore original alignment from stack */ 
+0

고맙습니다! 나는 이것을 실제로 발견했으나, 나는 또한 그것이 존재했는지 확인하고 싶었다. :) – lindes

2

은 일반적으로 (하지만 보장 아래), 구조체의 멤버는 word으로 정렬 된입니다. 즉, 단어 크기보다 작은 필드는 전체 단어를 차지하도록 채워집니다.

그러나 구조체의 다음 멤버가 일 수도 있고이 같은 단어 안에 들어갈 수 있으면 컴파일러는 두 멤버를 같은 단어에 넣습니다. 이는 공간에 따라보다 효율적이지만 플랫폼에 따라 해당 구성원을 검색하는 것이 계산적으로 더 비쌀 수도 있습니다. 시그윈하에 GCC를 사용하여 내 32 비트 시스템이 프로그램

...

#include <iostream> 

struct foo 
{ 
    char a; 
    int b; 
    char c; 
}; 

int main(int argc, char** argv) 
{ 
    std::cout << sizeof(foo) << std::endl; 
} 

출력 '12'는 모두 문자 워드로 정렬하고 최대 4 바이트의 각각을 때문이다.

그러나

struct foo 
{ 
    char a; 
    char c; 
    int b; 
}; 

구조체로 전환 두 문자가 서로 이웃 한 단어에 들어갈 수 없기 때문에 출력이 '8'이다.

+0

단어가 맞지 않습니다. 그럴 경우, 두 번째 예에서'a'와'c' 모두 별도의 단어를 차지합니다. ;) – jalf

+0

@ jalf : 잘 잡으십시오, 나는 맨 위에 내 설명을 확장했습니다. 그 일이 생길 때 나는 싫어 ... 내가 말한 것과 내가 상충 한 것을 의미하는 것 : X –

4

포장은이며, 맞춤법은 다릅니다. 둘 다 언어의 범위를 벗어나며 각 구현에 고유합니다. 보세요 here.

0

메모리를 절약하기 위해 바이트를 압축 할 수 있습니다. 예를 들어, pack (2)은 2 바이트 경계를 유지하기 위해 바이트보다 긴 멤버를 2 바이트로 압축하여 모든 패딩 멤버가 2 바이트 길이가되도록 지시합니다. 때때로 패킹은 특정 크기를 예상하는 표준 통신 프로토콜의 일부로 사용됩니다. 당신이가 될 구조체의 크기에 의존하는 경우, 컴파일러는 단어로 일을 처리

Padding is only inserted when a structure member is followed by a member with a larger alignment requirement or at the end of the structure. By changing the ordering of members in a structure, it is possible to change the amount of padding required to maintain alignment. For example, if members are sorted by ascending or descending alignment requirements a minimal amount of padding is required. The minimal amount of padding required is always less than the largest alignment in the structure. Computing the maximum amount of padding required is more complicated, but is always less than the sum of the alignment requirements for all members minus twice the sum of the alignment requirements for the least aligned half of the structure members.

Although C and C++ do not allow the compiler to reorder structure members to save space, other languages might.

구조체의에 있기 때문에, 때때로주의해야 케어 : 여기에 위키 백과는 C/C++ 및 패딩에 대해 말해야하는 것입니다 특정 크기. 예를 들어, char vs int 정렬.

0

그들은 기본적으로 포장되어 있지 않으며 컴퓨터가 설정되는 방법에 따라 단어가 정렬됩니다. 당신이 그들을 포장하고 싶다면. 그럼 당신은이처럼 구조체 선언의 끝에서 __attribute__((__packed__))을 사용할 수 있습니다 그리고

struct abc { 
    char a; 
    int b; 
    char c; 
}__attribute__((__packed__)); 

struct abc _abc; 

_abc을 위해 포장됩니다.

참조 : 무슨 일이 일어나고 있는지에 대한 단서를 제공 할 수 있습니다 동일한 구조의 변화의 일부 출력을 보는 http://www.grok2.com/structure_packing.html

0

. this을 읽은 후에, 내가 잘못 이해하지 못한다면, 작은 유형은 단어 길이가되도록 채워질 것입니다. 내 환경 출력에서 ​​

struct Foo { 
    char x ; // 1 byte 
    int y ; // 4 byte 
    char z ; // 1 byte 
    int w ; // 4 byte 
}; 
struct FooOrdered { 
    char x ; // 1 byte 
    char z ; // 1 byte 
    int y ; // 4 byte 
    int w ; // 4 byte 
}; 


struct Bar { 
    char x ; // 1 byte 
    int w ; // 4 byte 
}; 
struct BarSingleType { 
    char x ; // 1 byte 
}; 

int main(int argc, char const *argv[]) { 
    cout << sizeof(Foo) << endl; 
    cout << sizeof(FooOrdered) << endl; 
    cout << sizeof(Bar) << endl; 
    cout << sizeof(BarSingleType) << endl; 
    return 0; 
} 

이 같았다 :

16 
12 
8 
1 
관련 문제