해당 포스팅은 MSDN의 설명을 보다 다듬은 글입니다.
원본을 참조하고 싶으면 MSDN을 참조하세요.
사용할 Code
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential, Pack = 0)]
struct ExampleStruct
{
public byte b1;
public byte b2;
public int i3;
}
public class Example
{
public unsafe static void Main()
{
ExampleStruct ex = new ExampleStruct();
byte* addr = (byte*)&ex;
Console.WriteLine("Size: {0}", sizeof(ExampleStruct));
Console.WriteLine("b1 Offset: {0}", &ex.b1 - addr);
Console.WriteLine("b2 Offset: {0}", &ex.b2 - addr);
Console.WriteLine("i3 Offset: {0}", (byte*)&ex.i3 - addr);
}
}
Pack 필드는 처음 보면 다소 난해할 수 있는 기준인데,
기준을 한줄로 설명하자면.
'해당 바이트 수 안에서 struct 를 포함할 수 있는가?' 로 설명할 수 있다.
1. PACK = 0
Pack = 0 입력 시 출력값은 위와 같다.
Pack = 0 입력 시 구조체의 크기는 8 바이트로 나타나는데,
이는 필드중 가장 큰 바이트 (위 예제는 int 형으로 4 Byte)
에 맞춰 지기 때문에.
위 struct 의 메모리 구조는 다음 그림과 같다.
위와 같은 상황에서는 가장 큰 필드가 int 이기 때문에.
만약 8 바이트를 넘어가면 'int' 형의 크기인
+4 바이트씩 추가되는 것을 알 수있다.
2. PACK = 1
Pack 1 은 순수하다.
경계값이 1 바이트이다.
곧이 곧대로 들어간다.
3. PACK = 2
Pack 2 는 경계값이 2 바이트 지점이다.
위는 13 바이트이지만, 2바이트 단위로 경계가 끝나야 하기에
1 바이트의 패딩값을 추가하여서
13 바이트 짜리를 → 14 바이트로 교정한다.
1~9 바이트까지는 순서대로 들어가나, 10번째 메모리 주소는 padding 으로 채워지고.
11 ~ 14 번째 주소는 int 형이 들어감을 암시적으로 유추할 수 있다.
4. PACK = 4
이제 슬슬 규칙성이 보인다.
PACK 4 일때 위와 같은 식을 넣으면 당연히 4의 배수 경계값인 16이 도출될 것이다.
Padding 은 9 ~ 12 까지 3개가 들어간다.
5. PACK = 8~
Pack 8 이상 부터는 무의미 해 보일 수 있으나,
우리가 평소에 8 byte 이하의 형식만 사용해서 그렇게 보일 수 도 있다.
(double, int 등.)
decimal 은 16byte 의 크기를 지니는데, 이를 Pack 8 이상의 값에서도 조금 다르게 보일 것이다.
기본적으로 18 byte
pack = 4 일 때
byte 1, byte 2, padding 1, padding 2, decimal
순서로 배치되어 Size = 20
pack = 8 일 때
byte 1, byte 2, padding 1 ~ 6, decimal
순서로 배치되어 Size = 24
'Programming > C#' 카테고리의 다른 글
[C#] 반복문 캐싱 최적화 (0) | 2021.07.14 |
---|---|
[C#] Task .Wait() vs await 차이점 (0) | 2021.05.04 |
[C#] Struct 마샬링 및 사용법 (0) | 2021.04.15 |
[C#] C# 에서 대괄호가 가지는 의미, (사전 정의된 속성, 특성) (0) | 2021.04.03 |
[C#] async & await 을 lamdba 에서 사용시 오류 (0) | 2021.03.19 |