본문 바로가기

프로그램&DB/C#

[C# 강좌] C# 프로그래밍 #10- 구조체

3.3 구조체

3.3.1 구조체(structure) 소개

구조체를 사용하는 목적은 자료구조를 표현하기 위해서 있다. 기본적인 형태와 특징은 클래스와 비슷하다. 클래스와 마찬가지로 인터페이스에 대한 상속을 지원하며 메서드를 가질 수 있는 반면, 자료의 타입이 값 형태(Value Type)으로 지정된다. 이는 데이터에 대한 접근이 stack에 바로 접근해서 데이터를 가져올 수 있는 반면, 참조 형식(Reference Type)의 경우 stack에 접근해서 클래스의 Heap상의 위치에 대한 참조를 가져와야만 한다. 따라서, 간단한 자료 구조에 대한 표현이나 데이터형이 필요할 경우 구조체로 만드는 것이 성능면에서 유리하다는 것을 알 수 있다.

 구조체의 기본 형식은 다음과 같다.

/속성/

/엑세스 한정자/ struct [구조체 이름] [:interfaces]{}

 

* 구조체는 생성자, 상수, 필드, 메서드, 속성, 인덱서, 연산자, 이벤트 및 중첩 형식을 포함할 수 있다.

 

3.3.2 간단한 자료구조의 표현

한 점을 나타내는 포인터라는 구조체를 생각해보자.

 

 

 

3.3.3 속성

StructLayout LayoutKind열거자로 초기화되는데 LayoutKind의 멤버는 표와 같다.

멤버이름

             

Auto

런타임에 자동으로 레이아웃 선택. 관리되는 코드 외부에 노출시킬 수 없다.

Explict

관리되지 않는 메모리에 있는 각 멤버에 대한 정확한 위치 제어. 각 멤버는 FieldOffset 속성을 이용하여 나타낸다.

Sequential

관리되지 않는 메모리로 개체의 멤버를 보낼 때 Pack 속성에 따라 데이터 필드 맞춤을 지정 순서대로 배치한다.

 

 

3.3.4 Union 표현

  C C++를 배운적이 있다면 union이라는 키워드를 이용하여 만드는 공용체라는 것에 대해서 잘 알고 있을 것이다. Win32 API를 사용할 경우 매개변수 타입이 지정된 경우가 존재하는데, 이 경우 매개변수 타입을 만들어 낼 때 생기는 문제를 해결하기 위해 구조체의 StructLayout FieldOffset 속성(Attribute)를 이용하여 표현이 가능하다.

 

다음 예제는 구조체를 이용해 공용체를 흉내내 본 것이다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

28

30

31

32

33

34

35

36

using System;

using System.Collections.Generic;

using System.Text;

using System.Runtime.InteropServices;

 

namespace Union_Sample1

{

    class Program

    {

        static void Main(string[] args)

        {

            Union _union;   //구조체 선언

            _union.i = 0;   //구조체내 변수 i 초기화

            //byte변수들을 모두 1로 선언

            _union.b1 = _union.b2 = _union.b3 = _union.b4 = 1;

 

            Console.WriteLine(_union.i);

            System.Console.Read();

        }

    }

 

    [StructLayout(LayoutKind.Explicit)]

    public struct Union

    {

        [FieldOffset(0)]    //메모리내 시작 위치

        public int i;

        [FieldOffset(0)]    //0에서 시작

        public byte b1;

        [FieldOffset(1)]    //1에서 시작

        public byte b2;

        [FieldOffset(2)]    //2에서 시작

        public byte b3;

        [FieldOffset(3)]    //3에서 시작

        public byte b4;

    }

}

 

[결과]

16843009

 

 예제 소스를 실행해 보면 결과가 “1684309”와 같이 나온다는 것을 알 수 있다. 예제 소스에서 int 형 변수 i 4바이트 정수로 0으로 초기화 되었다. 그리고 변수 b1, b2, b3, b4를 모두 1로 초기화 하였다. b1, b2, b3, b4 4개의 바이트를 붙여서 나열해 비트(bit)형태로 표현해 보면 “00000001 00000001 00000001 00000001”과 같다는 것을 알 수 있다. 이를 10진수로 변환하면 “1684309”가 된다는 것을 알 수 있을 것이다. 결과적으로 int 형 변수 i의 값을 byte형 변수 4개가 공유하여 이용한다는 것을 이해할 수 있을 것이다