본문 바로가기
C#

구조체 배열 선언 시 메모리에서 일어나는 과정

by Oz Driver 2025. 7. 2.

 

구조체 배열을 선언하면 메모리 관점에서 어떤 일이 발생하는지 그 과정에 대해 한번 알아보겠습니다.

 

예제 코드

public struct StageData
{
    public int ballSpeed;
    public int blockColumn;
    public int blockRow;
}

StageData[] arr = new StageData[5];

 

배열은 힙(Heap) 에 생성

•  StageData[]는 참조 타입이므로 힙에 5개짜리 배열 공간이 생성됩니다.

•  그리고 StageData는 구조체(값 타입) 이므로, 배열 안에는 구조체가 들어갑니다. 

•  즉, 힙에 구조체 5개 짜리 데이타 공간이 생성되는 것입니다. 

 

각 요소는 자동 초기화

•  new StageData[5]를 하면, C#은 각 구조체를 default 값으로 자동 초기화합니다.

•  따라서, arr[0]부터 arr[4]까지는 모두 다음 값으로 초기화됩니다. 

•  만약 구조체 안에 참조 타입 필드가 있으면, 그 값은 null로 초기화됩니다.

ballSpeed = 0
blockColumn = 0
blockRow = 0

 

new에 공간을 생성하거나, 스택이라면 해당 크기 만큼 공간을 사용할 수 있도록 하는 역할만을 합니다. 

그리고 new 뒤에 따라오는 [ ] 나 ( ) 또는 { } 로 default 생성자 등을 호출하여 값을 자동 초기화합니다. 

 

// 컴파일 오류 (X)
StageData stageData = new StageData;

 

만약, new 가 값을 초기화하는 기능까지 있다면, 위와 같은 코드가 성립되어야 하는데 이런 코드는 없습니다.

즉, new 단독으로는 쓰일 수가 없고 뒤에 초기화하는 무언가가 반드시 뒤따라 오게 되어 있습니다. 그렇게 때문에 흔히 new 로 초기화 라는 말을 하는데, 엄밀히 말하면 new 로 먼저 공간 (참조 형식이면 힙에 동적으로 생성, 값 형식이라면 스택에 공간을 점유) 을 마련하고 초기화 라는 말이 더 정확합니다만, 대부분은 (거의 모두에 가까움) 이렇게 말하지 않기 때문에 우리는 이것을 분리해서 잘 생각하지 않게 되는 것 같습니다. 

 

구조체 필드에 값 대입

어쨌거나, new StageData[5] 로 구조체의 각 필드는 0 으로 자동 초기화된 상태입니다.

이제, 원하는 값으로 초기화시켜야 합니다. 

new StageData { ballSpeed = 5, blockColumn = 5, blockRow = 3 };

 

여기서 new 는 구조체 StageData 를 스택 또는 레지스터에 임시 저장 보관소를 만드는 역할을 합니다. 

공간만 마련된 상태이기 때문에, 이제 값을 채워넣어야 합니다.

다음 코드가 그 역할을 합니다.

 

{ ballSpeed = 5, blockColumn = 5, blockRow = 3 };

 

대입 연산자로 값 복사

이제 힙에 할당된 각 구조체에 값을 채워넣어야 합니다. 그리고 그 코드는 다음과 같습니다.

arr[0] = new StageData { ballSpeed = 5, blockColumn = 5, blockRow = 3 };

 

위 코드를 쪼개서 살펴보면, 

new StageData { ballSpeed = 5, blockColumn = 5, blockRow = 3 };

 

임시로 생성한 메모리 공간에 값을 채워넣은 후에 (이미 위에서 한번 설명했음)

arr[0] =

 

arr[0] 에 값을 대입합니다. 이 때 arr[0] 는 구조체이므로 값 복사가 일어납니다. 

결과적으로 힙 메모리에 생성된 구조체 arr[0] 에 값이 채워집니다.  

 

최종 코드

지금까지 설명한 내용을 코드로 작성하면 다음과 같습니다.

StageData[] stageDate = new StageData[5];
stageDate[0] = new StageData { ballSpeed = 5, blockColumn = 5, blockRow = 3 };
stageDate[1] = new StageData { ballSpeed = 6, blockColumn = 6, blockRow = 3 };
stageDate[2] = new StageData { ballSpeed = 7, blockColumn = 7, blockRow = 4 };
stageDate[3] = new StageData { ballSpeed = 8, blockColumn = 8, blockRow = 4 };
stageDate[4] = new StageData { ballSpeed = 9, blockColumn = 9, blockRow = 5 };

 

만약, 선언과 동시에 값을 초기화할 경우라면 다음과 같습니다. 

StageData[] stageDate = new StageData[5]
{
    new StageData { ballSpeed = 5, blockColumn = 5, blockRow = 3 },
    new StageData { ballSpeed = 6, blockColumn = 6, blockRow = 3 },
    new StageData { ballSpeed = 7, blockColumn = 7, blockRow = 4 },
    new StageData { ballSpeed = 8, blockColumn = 8, blockRow = 4 },
    new StageData { ballSpeed = 9, blockColumn = 9, blockRow = 5 },
};

 

정리

지금까지 구조체 배열 선언과 초기화에 대해 살펴보았습니다. 

처음에는 코드가 눈에 잘 들어오지 않지만 지금까지 설명한 내용을 이해하신다면, 전체 코드가 눈에 익숙해지실 거라 생각됩니다.