IT이야기

C의 구조 메모리 레이아웃

cyworld 2022. 5. 18. 21:59
반응형

C의 구조 메모리 레이아웃

나는 C# 경력이 있다.나는 C와 같은 저급한 언어에 아주 신참이다.

C#에서는struct의 메모리는 컴파일러에 의해 기본적으로 배치된다.컴파일러는 데이터 필드를 다시 정렬하거나 필드 사이에 추가 비트를 암묵적으로 패딩할 수 있다.그래서, 나는 정확한 레이아웃을 위해 이 동작을 재정의하기 위해 몇 가지 특별한 속성을 지정해야 했다.

AFAIK, C가 a의 메모리 레이아웃을 다시 정렬하거나 정렬하지 않음struct결하ha여 하지만, 하지만, 나는 매우 찾기 힘든 약간의 예외가 있다고 들었어.

C의 메모리 레이아웃 동작은 무엇인가?무엇을 재정렬/정렬해야 하며, 그렇지 않아야 하는가?

에 따라는 규칙는 안 되는 경우)이 있다.#pragma pack또는 이와 유사한 것)은 다음과 같다.

  • 구조 구성원은 선언된 순서대로 저장된다.(이것은 앞에서 언급한 바와 같이 C99 표준에서 요구하는 사항이다.)
  • 필요한 경우, 정확한 정렬을 위해 각 구조체 부재 앞에 패딩을 추가한다.
  • 각 원시 유형 T는 다음과 같이 정렬되어야 한다.sizeof(T)바이트 수

따라서 다음과 같은 구조로 간주된다.

struct ST
{
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};
  • ch1오프셋 0에 있음
  • ...을 정렬하기 위해 패딩 바이트를 삽입하다.
  • s오프셋 2로
  • ch2간격띄우기 4에 있으며, s 바로 뒤에 있음
  • 정렬하기 위해 패딩 3바이트 삽입...
  • ll오프셋8로
  • ill 직후에 오프셋 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;

C에서 컴파일러는 모든 원시 유형에 대해 어느 정도 정렬을 지시할 수 있다.전형적으로 선형은 타입의 크기 입니다.그러나 이는 전적으로 구현에 특정한 것이다.

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

모든 원격 현대 컴파일러 구현#pragma pack패딩을 제어할 수 있고 프로그래머에게 ABI를 준수하도록 맡긴다. (그러나 이는 엄격히 비표준적이다.)

C99 §6.7.2.1부터:

12 구조 또는 조합 객체의 각 비비트 필드 구성원은 그 유형에 적합한 구현 정의 방식으로 정렬된다.

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

데이터 정렬에 대한 이해를 높이기 위해 데이터 구조 정렬 위키백과 기사를 읽는 것으로 시작할 수 있다.

위키백과 기사:

데이터 정렬이란 데이터를 단어 크기의 일부 배수와 같은 메모리 오프셋에 넣는 것을 의미하며, CPU가 메모리를 처리하는 방식에 따라 시스템의 성능이 향상된다.데이터를 정렬하려면 마지막 데이터 구조의 끝과 다음 데이터 구조의 시작, 즉 데이터 구조 패딩 사이에 의미 없는 바이트를 삽입해야 할 수도 있다.

GCC 문서의 6.54.8 구조 포장 실용주의:

Microsoft Windows 컴파일러와의 호환성을 위해 GCC는 이후에 정의된 구조(영폭 비트필드 제외), 유니언 및 클래스의 구성원의 최대 정렬을 변경하는 일련의 #pragma 명령을 지원한다.아래 n 값은 항상 2의 작은 검정력이어야 하며 새로운 정렬을 바이트 단위로 지정한다.

  1. #pragma pack(n)새 정렬을 간단히 설정한다.
  2. #pragma pack()컴파일이 시작될 때 적용되는 정렬로 설정하십시오(명령줄 옵션 -fpack-struct[=] 코드 생성 옵션 참조).
  3. #pragma pack(push[,n])내부 스택에서 현재 정렬 설정을 누른 다음 선택적으로 새 정렬을 설정하십시오.
  4. #pragma pack(pop)정렬 설정을 내부 스택의 맨 위에 저장된 설정으로 복원(그리고 해당 스택 항목을 제거).참고:#pragma pack([n])이 내부 스택에 영향을 미치지 않으므로, 이 스택을 가질 수 있다.#pragma pack(push)뒤이어 복수하다.#pragma pack(n)단일 항목으로 마무리된 인스턴스#pragma pack(pop).

i386 및 powerpc와 같은 일부 타겟은 ms_struct를 지원한다.#pragma문서화된 구조물에 따르면__attribute__ ((ms_struct)).

  1. #pragma ms_struct on선언된 구조물의 레이아웃을 켜십시오.
  2. #pragma ms_struct off선언된 구조물의 레이아웃을 끄십시오.
  3. #pragma ms_struct reset기본 레이아웃으로 돌아가십시오.

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

반응형