C#은 기본적으로 StructLayout 가 정해져 있습니다.
클래스는 [StructLayout(LayoutKind.Auto, Pack = 0)]
구조체는 [StructLayout(LayoutKind.Sequential, Pack =0)]
평소엔 신경쓰지 않아도 되지만 C, C++ 혹은 서버와 통신 등 메모리를 맞춰줘야 될 때
사용되는 기능이니 이런 것이 있다는 것만 알면 될거 같습니다.
아래 코드는 C#으로 C, C++ 포인터를 흉내내어 메모리 참조를 해본 코드입니다.
using System;
using System.Runtime.InteropServices; // [StructLayout ] 선언에 필요합니다.
//참고 설명 https://www.csharpstudy.com/DevNote/Article/10
//*****************************************************************
//
// 기본값
// class : [StructLayout(LayoutKind.Auto, Pack = 0)]
// struct : [StrcutLayout(LayoutKind.Sequential, Pack = 0)]
//
// Pack : 0이면 자동 세팅에 따릅니다. (0, 1, 2, 4, 8, 16... 128 까지 2의 배수만 가능합니다.)
// 1 이상이면 Pack과 타입 크기 중 가장 큰 단위에 따라 패딩을 넣어줍니다.
//
// ex)
// [StructLayout(LayoutKind.Sequential, Pack = 0)]
// struct MyStruct
// {
// public int i; // 4
// public double d; // 8
// public byte b; // 1
// }
//
// 가장 큰 사이즈에 맞추어 크기가 조절 됩니다.
// Pack = 0 이면 가장 큰 사이즈 byte
// sizeof(MyStruct) == 24
//
// i = (0~3)
// 패딩 = (4~7)
// d = (8~15)
// b = (16)
// 패딩 = (17~23)
//
// Pack = 1 이면 1에 가까운 타입에 맞추어집니다. 즉 byte 중심이 되며
// i = (0~3), d = (4~11), b = (12) 가 되어 0~12까지 size = 13이 됩니다.
//
// LayoutKind.Sequential : 메모리상에 순차적으로 저장합니다.
// Auto : 힙 영역에 자동으로 저장합니다.
// Explicit : 직접 메모리 영역을 지정해줍니다.
// 변수에 [FieldOffset()] 식으로 지정해주어야 합니다.
//
//****************************************************************
namespace StructLayout
{
class Program
{
[StructLayout(LayoutKind.Explicit, Pack = 1)] //int형 4에 맞춰집니다.
public struct Test
{
[FieldOffset(0)]
public int value; // 4 (0000 0000, 0000 0000, 0000 0000, 0000 0000)
[FieldOffset(0)]
public byte value1; // (0000 0000 ____ ____ ____ ____ ____ ____)
[FieldOffset(1)]
public byte value2; // (____ ____ 0000 0000 ____ ____ ____ ____)
[FieldOffset(2)]
public byte value3; // (____ ____ ____ ____ 0000 0000 ____ ____)
[FieldOffset(3)]
public byte value4; // (____ ____ ____ ____ ____ ____ 0000 0000)
}
//c언어의 포인터를 흉내낼 수 있습니다!
static unsafe void Main(string[] args) //unsafe : 포인터 사용지 설정이 필요합니다.
{
Test test = new Test();
Console.WriteLine("sizeof(TEST) : {0}", sizeof(Test));
//c, c++언어의 포인터
int* startAddress = (int*)&test;
//1100 1100, 0000 0100, 0000 0001, 0000 0001
test.value = (1 << 31) | (1 << 30) | (1 << 28) | (1 << 27) | //1100 1100 ____ ____ ____ ____ ____ ____
(1 << 18) | //1100 1100 0000 0100 ____ ____ ____ ____
(1 << 8) | //1100 1100 0000 0100 0000 0001 ____ ____
1; //1100 1100 0000 0100 0000 0001 0000 0001
Console.WriteLine("test.value : {0}", Convert.ToString(test.value, 2)); //2진수로 출력
Console.WriteLine("test.value1 : {0}", Convert.ToString(test.value1, 2)); //2진수로 출력 0000 0001
Console.WriteLine("test.value3 : {0}", Convert.ToString(test.value2, 2)); //2진수로 출력 0000 0001
Console.WriteLine("test.value2 : {0}", Convert.ToString(test.value3, 2)); //2진수로 출력 0000 0100
Console.WriteLine("test.value4 : {0}", Convert.ToString(test.value4, 2)); //2진수로 출력 1100 1100
}
}
}
'C# > Console' 카테고리의 다른 글
[C#] 프로세스 실행 및 대기 (Process.Start , Process.WaitForExit) (0) | 2024.01.30 |
---|---|
[C#] 금액 (숫자) -> 한글 (원)로 변환하기 (0) | 2023.01.23 |
[C#] 제이슨 JSON (JObject, JArray, Serialize, Deserialize) (0) | 2022.06.30 |
[C#] 내 아이피 주소 보기 IPv4, IPv6 (0) | 2022.03.07 |
[C#] Regex.IsMatch 를 이용한 문자 존재 여부 판별 (정규식 작성) (0) | 2022.03.01 |