Nice programing

C의 구조 메모리 레이아웃

nicepro 2020. 10. 15. 21:39
반응형

C의 구조 메모리 레이아웃


C # 배경이 있습니다. 저는 C와 같은 저수준 언어의 초보자입니다.

C #에서 struct의 메모리는 기본적으로 컴파일러에 의해 배치됩니다. 컴파일러는 데이터 필드를 재정렬하거나 암시 적으로 필드 사이에 추가 비트를 채울 수 있습니다. 따라서 정확한 레이아웃을 위해이 동작을 재정의하기 위해 몇 가지 특수 속성을 지정해야했습니다.

AFAIK, C는 struct기본적 으로 a의 메모리 레이아웃을 재정렬하거나 정렬하지 않습니다 . 그러나 찾기가 매우 어려운 약간의 예외가 있다고 들었습니다.

C의 메모리 레이아웃 동작은 무엇입니까? 무엇을 재정렬 / 정렬해야합니까?


C에서 컴파일러는 모든 기본 유형에 대해 일부 정렬을 지시 할 수 있습니다. 일반적으로 정렬은 유형의 크기입니다. 그러나 그것은 완전히 구현에 따라 다릅니다.

패딩 바이트가 도입되어 모든 객체가 올바르게 정렬됩니다. 재주문은 허용되지 않습니다.

아마도 모든 원격 최신 컴파일러 #pragma pack는 패딩을 제어하고 ABI를 준수하도록 프로그래머에게 맡기는 것을 구현합니다. (하지만 엄격하게 비표준입니다.)

C99 §6.7.2.1에서 :

12 구조체 또는 공용체 객체의 비트 필드가 아닌 각 멤버는 해당 유형에 적합한 구현 정의 방식으로 정렬됩니다.

13 구조체 객체 내에서 비트 필드가 아닌 멤버와 비트 필드가 상주하는 단위에는 선언 된 순서대로 증가하는 주소가 있습니다. 적절하게 변환 된 구조체 객체에 대한 포인터는 초기 멤버 (또는 해당 멤버가 비트 필드 인 경우 해당 멤버가 상주하는 단위)를 가리키고 그 반대의 경우도 마찬가지입니다. 구조 객체 내에 이름없는 패딩이있을 수 있지만 시작 부분에는 없습니다.


구현에 따라 다르지만 실제로 규칙 #pragma pack은 다음과 같습니다.

  • 구조체 멤버는 선언 된 순서대로 저장됩니다. (앞에서 언급했듯이 C99 표준에서 필요합니다.)
  • 필요한 경우 올바른 정렬을 보장하기 위해 각 구조체 멤버 앞에 패딩이 추가됩니다.
  • 각 기본 유형 T에는 sizeof(T)바이트 정렬이 필요합니다 .

따라서 다음 구조체가 주어집니다.

struct ST
{
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};
  • ch1 오프셋 0에 있습니다.
  • 패딩 바이트가 삽입되어 정렬됩니다.
  • s 오프셋 2에서
  • ch2 s 바로 뒤에 오프셋 4에 있습니다.
  • 정렬을 위해 3 개의 패딩 바이트가 삽입됩니다.
  • ll 오프셋 8에서
  • i ll 바로 뒤에 오프셋 16에 있습니다.
  • 4 개의 패딩 바이트가 끝에 추가되어 전체 구조체가 8 바이트의 배수가됩니다. 나는 이것을 64 비트 시스템에서 확인했다 : 32 비트 시스템은 구조체가 4 바이트 정렬을 갖도록 허용 할 수있다.

sizeof(ST)24도 마찬가지 입니다.

패딩을 피하기 위해 멤버를 재 배열하여 16 바이트로 줄일 수 있습니다.

struct ST
{
   long long ll; // @ 0
   int i;        // @ 8
   short s;      // @ 12
   char ch1;     // @ 14
   char ch2;     // @ 15
} ST;

데이터 정렬에 대한 더 나은 이해를 위해 데이터 구조 정렬 위키피디아 문서읽는 것으로 시작할 수 있습니다 .

로부터 위키 피 디아 기사 :

Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.

From 6.54.8 Structure-Packing Pragmas of the GCC documentation:

For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives which change the maximum alignment of members of structures (other than zero-width bitfields), unions, and classes subsequently defined. The n value below always is required to be a small power of two and specifies the new alignment in bytes.

  1. #pragma pack(n) simply sets the new alignment.
  2. #pragma pack() sets the alignment to the one that was in effect when compilation started (see also command line option -fpack-struct[=] see Code Gen Options).
  3. #pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.
  4. #pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).

Some targets, e.g. i386 and powerpc, support the ms_struct #pragma which lays out a structure as the documented __attribute__ ((ms_struct)).

  1. #pragma ms_struct on turns on the layout for structures declared.
  2. #pragma ms_struct off turns off the layout for structures declared.
  3. #pragma ms_struct reset goes back to the default layout.

참고URL : https://stackoverflow.com/questions/2748995/struct-memory-layout-in-c

반응형