C#에서 포인터를 사용하려면 반드시 unsafe 한정자가 필요합니다. 그리고 배열 요소를 포인터로 접근하려면 fixed 키워드를 함께 사용해야 합니다.
그 이유는 배열과 포인터의 데이터 타입이 서로 다르기 때문입니다. 예를 들어 int[] 타입은 int* 타입과 동일하지 않습니다. 가비지 컬렉터가 배열을 메모리 내에서 이동시킬 수 있으므로, fixed 키워드를 사용하면 실행 중에 배열이 메모리에서 이동하지 않도록 고정할 수 있습니다.
예제
다음 프로그램은 포인터를 사용하여 배열 요소에 접근하는 방법을 보여줍니다.
using System;
namespace PointerDemo {
class Example {
public unsafe static void Main() {
int[] array = {55, 23, 90, 76, 9, 57, 18, 89, 23, 5};
int n = array.Length;
fixed(int *ptr = array)
for ( int i = 0; i < n; i++) {
Console.WriteLine("array[{0}] = {1}", i, *(ptr + i));
}
}
}
}실행 결과
위 프로그램을 실행하면 다음과 같은 결과가 출력됩니다.
array[0] = 55 array[1] = 23 array[2] = 90 array[3] = 76 array[4] = 9 array[5] = 57 array[6] = 18 array[7] = 89 array[8] = 23 array[9] = 5
코드 설명
위 프로그램의 동작을 단계별로 살펴보겠습니다.
먼저 배열에는 int 타입의 값 10개가 저장되어 있습니다. fixed 키워드를 사용하면 포인터 ptr이 배열의 시작 위치를 가리키게 되며, 이때 배열은 메모리에 고정됩니다.
이후 for 루프를 통해 포인터 산술 연산(*(ptr + i))으로 각 배열 요소에 순차적으로 접근하고, 모든 값을 화면에 출력합니다. 해당 코드는 다음과 같습니다.
int[] array = {55, 23, 90, 76, 9, 57, 18, 89, 23, 5};
int n = array.Length;
fixed(int *ptr = array)
for ( int i = 0; i < n; i++) {
Console.WriteLine("array[{0}] = {1}", i, *(ptr + i));
}참고로 포인터를 사용하는 코드는 안전성 검증을 우회하기 때문에 프로젝트 설정에서 안전하지 않은 코드 허용(Allow unsafe code) 옵션을 활성화해야 컴파일할 수 있습니다.