c#에서 포인터를, unsafe
unsafe 키워드를 사용해야 할 일이 그렇게 많지는 않겠지만, WinAPI를 다뤄야 한다면 피해갈 수 없는 부분이므로 소개해 봅니다.
물론 닷넷을 사용하면서 포인터를 사용한다는 것은 닷넷의 철학에 역행하는 일이 되겠습니다만, 어쨌든 winapi를 호출한다던가 할 일이 있다면 포인터를 사용해야만 합니다. 이 아티클은 포인터를 사용하기 위한 키워드인 unsafe와, unsafe를 사용한 코드를 컴파일하는 방법에 대해 설명합니다.
우리는 포인터가 필요하다
Kenial 은 처음으로 c/c++을 공부하는 사람이 가장 이해하기 어려운 부분이 포인터가 아닐까. 라고 생각한다. 시스템에 접근할 수 있는 가장 저수준의 도구이면서, '기계의 입장에서' 생각하지 않으면 도저히 이해할 수 없는 부분이 아닐까.
사 실 포인터 없이도 좋은 프로그램을 만들 수는 있다. 하지만 우리는 아직도 WinAPI를 벗어날 수 없고, WinAPI와 상호작용할 수 있는 코드를 만들고 싶다면, 포인터는 필요하다. 물론 포인터 없이도 가능한 일이기는 하지만, 그만큼 코드가 늘어난다거나 지저분한 코드를 얻게 되는 등의 댓가를 치뤄야 하므로...
unsafe 키워드
msdn의 c# programmer's reference를 참고하면, unsafe를 이렇게 설명하고 있다 :
The unsafe keyword denotes an unsafe context, which is required for any operation involving pointers.
말 그대로, unsafe한 내용을 표시할 때 사용되는 키워드이다. 일단 간단한 다음 코드를 보자 :
| | |
| int a; | |
| | |
a를 참조하는 포인터 변수 b를 선언하는 코드이다. c#에서 &과 *이 횡행하는 코드를 봐서 당황스러울 수는 있겠으나, 막상 컴파일을 해 보면 문법 에러는 발생하지 않는다. 다음과 같은 에러가 발생할 것이다 : 포인터는 안전하지 않은 컨텍스트 안에서만 사용할 수 있습니다.
여기서 말하는 안전하지 않은 컨텍스트'를 만드는 기능을 가진 키워드가 바로 unsafe인 것이다. 다음과 같이 코드를 고치고 다시 컴파일 해 보도록 하자 :
| | |
| unsafe { | |
| | |
잘 컴파일되는가? 천만의 말씀이다. 이번에는 이런 에러가 발생할 것이다 : 안전하지 않은 코드는 /unsafe를 사용하여 컴파일하는 경우에만 나타날 수 있습니다.
기본적으로 마이크로소프트에서는 '안전하지 않은 코드' 를 사용하는 것을 무척이나 싫어하는게 아닐까 하는 생각이 든다. (물론 정말 '안전하지 않은 코드'라고 한다면 당연하지만..) unsafe 키워드를 사용한 프로그램은 컴파일러에서 /unsafe 옵션을 주어야 하며, 이는 프로젝트 속성을 바꿔주면 된다.
'안전하지 않은 코드 블록 허용' 항목을 true로 세팅한다.
이와 같이 설정을 바꾸면 코드가 제대로 컴파일되는 것을 확인할 수 있을 것이다.
unsafe 선언의 여러 형태
unsafe는 위와 같이 코드 블록에만 사용할 수 있는 것은 아니다.
| | |
| unsafe private void ThisIsUnsafeFunction( void* pvVoid )
unsafe class UnsafeClass
unsafe delegate void* UnsafeEventHandler ( int* i );
unsafe event UnsafeEventHandler UnsafeEvent; | |
| | |
보시다시피, 함수나 클래스, 딜리게이트, 이벤트까지 사용 가능하다. 딜리게이트의 경우, 이벤트 핸들러의 파라메터나 리턴 값이 포인터일 경우에 unsafe 키워드를 사용해야 한다.
정리
포인터를 사용하기 위한 키워드인 unsafe에 대하여 간단히 알아보았습니다. 하지만 예전 c/c++ 처럼 포인터를 사용해서 객체를 전달하는 것 같은 일을 간단하게 수행할 수는 없고, 여러가지 제약이 있습니다. 물론 이것도 피해가는 방법이 있습니다만, 일단은 천천히 소개하기로 하죠.
그럼 : )
'TechLog' 카테고리의 다른 글
UTF8(Unicode) -> euc-kr 문자 셋으로 변환하기 (0) | 2008.08.27 |
---|---|
Managed Type, Unmanaged Type의 참조 (0) | 2008.08.26 |
성능 모니터의 카운터 이름이 숫자로 나올 경우 (0) | 2008.08.22 |
c#에서의 참조, ref 키워드 (0) | 2008.08.22 |
자동 로그온 유틸리티, AutoLogon (0) | 2008.08.21 |