source

C 구조의 메모리 얼라인

gigabyte 2022. 11. 19. 11:41
반응형

C 구조의 메모리 얼라인

32비트 머신을 사용하고 있기 때문에 메모리 얼라인먼트는 4바이트가 될 것입니다.예를 들어 다음과 같은 구조를 가지고 있습니다.

typedef struct {
    unsigned short v1;
    unsigned short v2;
    unsigned short v3;
} myStruct;

플레인 추가 사이즈는 6바이트이고 정렬 사이즈는 8바이트라고 생각합니다만,sizeof(myStruct)6이 반환됩니다.

하지만 내가 쓴다면:

typedef struct {
    unsigned short v1;
    unsigned short v2;
    unsigned short v3;
    int i;
} myStruct;

플레인 덧셈 사이즈는 10바이트, 정렬 사이즈는 12바이트, 그리고 이번에는sizeof(myStruct) == 12.

누가 차이점을 설명해 줄 수 있나요?

적어도 대부분의 머신에서 타입은 타입 자체와 같은 크기의 경계에만 정렬됩니다.[편집: 어레이를 작성할 수 있어야 하고 어레이에 패딩을 삽입할 수 없기 때문에 그 이상의 "더 이상의" 정렬을 요구할 수 없습니다.구현 시short2바이트라고 생각됩니다.int4 바이트

즉, 첫 번째 구조가 2바이트 경계에 정렬됩니다.모든 멤버는 각각2바이트이기 때문에 패딩은 삽입되지 않습니다.

두 번째 항목은 4바이트 경계에 정렬되는 4바이트 항목을 포함합니다.6바이트 앞에 2바이트의 패딩이 삽입되어 있습니다.v3그리고.i에 6바이트의 데이터가 표시됩니다.short2바이트의 패딩과 4바이트의 추가 데이터가 있습니다.int총 12개입니다.

다른 부재를 갖는다는 것은 잊으십시오.부재가 완전히 같은 2개의 구조체를 쓰는 경우에도 선언 순서가 다르면 각 구조체의 크기가 다를 수 있습니다(대부분 다를 수 있습니다).

예를 들어, 이걸 보세요.

#include <iostream>
using namespace std;
struct A
{
   char c;
   char d;
   int i; 
};
struct B
{
   char c;
   int i;   //note the order is different!
   char d;
};
int main() {
        cout << sizeof(A) << endl;
        cout << sizeof(B) << endl;
}

를 사용하여 컴파일합니다.gcc-4.3.4, 다음의 출력이 표시됩니다.

8
12

즉, 두 구조물이 같은 부재를 가지고 있어도 크기가 다릅니다!

IDEONE 코드 : http://ideone.com/HGGVl

결론은 표준에서는 패딩 방법에 대해 언급하지 않기 때문에 컴파일러가 자유롭게 결정을 내릴 수 있으며 모든 컴파일러가 같은 결정을 내릴 수 없다는 것입니다.

전제 조건:

sizeof(unsigned short) == 2
sizeof(int)            == 4

그럼 저는 개인적으로 다음 항목을 사용합니다(사용하시는 컴파일러는 다를 수 있습니다.

unsigned shorts are aligned to 2 byte boundaries
int will be aligned to 4 byte boundaries.


typedef struct
{
   unsigned short v1;    // 0 bytes offset
   unsigned short v2;    // 2 bytes offset
   unsigned short v3;    // 4 bytes offset
} myStruct;              // End 6 bytes.


// No part is required to align tighter than 2 bytes. 
// So whole structure can be 2 byte aligned.

typedef struct
{
    unsigned short v1;      // 0 bytes offset
    unsigned short v2;      // 2 bytes offset
    unsigned short v3;      // 4 bytes offset
    /// Padding             // 6-7 padding (so i is 4 byte aligned)
    int i;                  // 8 bytes offset
} myStruct;                 // End 12 bytes

// Whole structure needs to be 4 byte aligned.
// So that i is correctly aligned.

각 데이터 유형은 자체 크기의 메모리 경계에 맞춰야 합니다.비상대기상태short2바이트 경계에 정렬되어 있어야 합니다.int는 4바이트 경계상에 있어야 합니다.마찬가지로 a.long long8바이트 경계에 있어야 합니다.

두 번째 이유는sizeof(myStruct)존존 12 is is is is is is is is is is is 사이에 입니다.v3 ★★★★★★★★★★★★★★★★★」ii32살2번입니다.

위키피디아는 패딩과 정렬에 대해 상당히 명확하게 설명합니다.

우선 패딩의 자세한 내용은 컴파일러에 맡기지만 OS는 얼라인먼트 요건에 대해서도 몇 가지 규칙을 부과합니다.이 답변에서는 OS가 다를 수 있지만 gcc를 사용하고 있다고 가정합니다.

특정 구조물과 해당 요소가 차지하는 공간을 확인하려면 다음 규칙을 따릅니다.

첫째, 구조체는 항상 모든 데이터 유형에 대해 적절하게 정렬된 주소에서 시작된다고 가정합니다.

그런 다음 구조체의 모든 항목에 대해 다음을 수행합니다.

  • 한 최소 입니다.sizeof(element).
  • 요소의 정렬 요건은 요소의 베이스 유형의 정렬 요건입니다. 이것은, 「」, 「」, 「A」의 이 되는 것을 합니다.char[20]은 플레인()의 .char.

마지막으로 구조물 전체의 얼라인먼트 요건은 각 요소의 얼라인먼트 요건의 최대값이다.

gcc는 특정 요소 뒤에 패딩을 삽입하여 다음 요소(또는 마지막 요소에 대해 말하는 경우 구조체)가 올바르게 정렬되도록 합니다.메모리를 절약할 수 있다고 해도, 구조내의 요소의 순서를 재정렬 하는 일은 없습니다.

얼라인먼트 요건 자체도 조금 이상합니다.

  • 32비트 Linux에서는 2바이트의 데이터 타입에 2바이트의 정렬이 필요합니다(주소는 짝수여야 합니다).얼라인먼트를 가져야 는 4바이트로 ).0x0,0x4,0x8 ★★★★★★★★★★★★★★★★★」0xC보다 큰 4' 등)에도 적용됩니다double ★★★★★★★★★★★★★★★★★」long double를 참조해 주세요.
  • 32비트 Windows는 크기가 K바이트일 경우 K바이트 정렬이어야 한다는 점에서 더 엄격합니다., a, a가double can 、 in in in in in in in in in in in in in로 끝나는 할 수 .0x0 ★★★★★★★★★★★★★★★★★」0x8는 ""입니다.long double실제로는 12바이트이지만 4바이트 정렬되어 있습니다.
  • Linux와 윈도우즈 모두에서 64비트 시스템에서 K 바이트 유형은 K 바이트 정렬이어야 합니다. 한 번 말씀드리지만long double열여섯 살

기본적으로 값은 크기에 따라 정렬됩니다., 은 「」, 「2」와 .short 2바이트의 4바이트 값이 .4번입니다.int.

예에서는 보다 앞에 됩니다.i 확실하게 i4면 됩니다.

(구조 전체는 적어도 구조에서 가장 큰 값의 경계에 정렬되므로 구조가 4바이트 경계에 정렬됩니다.)

실제 규칙은 플랫폼에 따라 다릅니다.데이터 구조 정렬에 관한 Wikipedia 페이지에 자세한 내용이 기재되어 있습니다.

으로 (를 들어)수 .#pragma pack이치노

short를 , , 에 정렬할 수 .short따라서 마지막에 패딩을 추가할 필요가 없습니다.

32비트가 int, int(32비트) 사이에 하도록 단어 합니다.v3 ★★★★★★★★★★★★★★★★★」ii.

var의는 2,4 있는 뒤에 중를 이동시켰을 var는 4로 정렬되어 있습니다.따라서 int 뒤에 short 중 하나를 이동하면 주소가 액세스되는 크기의 배수(short는 2, ints는 4 등)가 됩니다.sizeof(mystruct)10이 되어야 .물론 이 모든 것은 사용하는 컴파일러와 컴파일러가 사용하는 설정에 따라 달라집니다.

표준에서는 완전한 타입의 구조 레이아웃에 대해서는 그다지 언급하지 않습니다.컴파일러에 따라 다릅니다.액세스하기 위해서는 경계에서 int가 필요하다고 판단했지만 쇼트용으로 서브 경계 메모리주소를 지정해야 하기 때문에 패딩할 필요가 없습니다.

언급URL : https://stackoverflow.com/questions/5435841/memory-alignment-in-c-structs

반응형