Introduction
- C#에서는 포인터를 제한된 범위에서 지원한다.
- 포인터 연산자의 종류와 역할은 아래와 같다.
&
: 메모리 주소 반환*
: 포인터 역참조->
: 멤버 액세스[]
: 요소 액세스
&
연산자
&
연산자는 피연산자의 주소를 반환한다.unsafe static void Main(string[] args) { int foo = 6; int* bar = &foo; Console.WriteLine($"{(long)bar:X2}"); // 실행할 때마다 값이 달라진다. } /* output: 65717DEBAC */
피연산자가
GC
의 영향을 받는 경우fixed 문
을 이용하여 고정 후 주소를 가져올 수 있다.unsafe static void Main(string[] args) { int[] foo = [1, 2, 3]; //int* bar = &foo[1]; // CS0212 fixed (int* bar = &foo[1]) { Console.WriteLine($"{(long)bar:X2}"); } } /* output: 1B99C9019F4 */
*
연산자
역참조 연산자
*
는 포인터가 가리키는 변수를 반환한다.
이를 이용해 데이터 작업을 수행할 수 있다.unsafe static void Main(string[] args) { int foo = 7; int* bar = &foo; Console.WriteLine(*bar); *bar = 10; Console.WriteLine(foo); } /* output: 7 10 */
->
연산자
멤버 액세스 연산자
->
는*
연산자와 멤버 액세스 식 (.
)을 결합한다.
다음 두 식은 같은 결과를 가져온다.pointer->member (*pointer).member
->
연산자는 아래와 같이 사용한다.public struct Foo { public int Bar; }
unsafe static void Main(string[] args) { Foo foo = new(); Foo* bar = &foo; Console.WriteLine((*bar).Bar); bar->Bar = 10; Console.WriteLine(foo.Bar); } /* output: 0 10 */
[]
연산자
type* p
의p[n]
액세스는*(p + n)
으로 계산된다.
n
은 암시적으로int
,uint
,long
,ulong
중 하나로 전환할 수 있는 형식이어야 한다.unsafe static void Main(string[] args) { int* foo = stackalloc int[3]; for (int i = 0; i < 3; i++) { foo[i] = i; } for (int i = 0; i < 3; i++) { Console.Write($"{foo[i]} "); } } /* output: 0 1 2 */
포인터 덧셈 (+
)
pointer + n
,n + pointer
는pointer + n * sizeof(T)
포인터를 반환한다.unsafe static void Main(string[] args) { int* ints = stackalloc int[] { 1, 3, 5, 7, 9, 11 }; int* foo = &ints[0]; int* bar = foo + 2; Console.WriteLine(*bar); Console.WriteLine(*++bar); } /* output: 5 7 */
포인터 뺄셈 (-
)
pointer - n
은pointer - n * sizeof(T)
포인터를 반환한다.unsafe static void Main(string[] args) { int* ints = stackalloc int[] { 1, 3, 5, 7, 9, 11 }; int* foo = &ints[5]; int* bar = foo - 2; Console.WriteLine(*bar); Console.WriteLine(*--bar); } /* output: 7 5 */
포인터끼리 뺄셈을 수행하는 경우 주소값을 연산하여 반환한다.
(pointer1 - pointer2) / sizeof(T)
값을 반환하며 형식은long
이다.unsafe static void Main(string[] args) { int* ints = stackalloc int[] { 1, 3, 5, 7, 9, 11 }; int* foo = &ints[5]; int* bar = foo - 3; var baz = foo - bar; Console.WriteLine(baz.GetType()); Console.WriteLine(baz); } /* output: System.Int64 3 */
포인터 비교
==
,!=
,>
,<
,>=
,<=
연산자는 포인터 비교에 사용 가능하며 피연산자의 주소를 비교한다.unsafe static void Main(string[] args) { int* ints = stackalloc int[] { 1, 3, 5, 7, 9, 11 }; int* foo = &ints[0]; int* bar = foo + 2; Console.WriteLine(foo == bar); Console.WriteLine(foo != bar); Console.WriteLine(foo > bar); Console.WriteLine(foo < bar); Console.WriteLine(foo >= bar); Console.WriteLine(foo <= bar); } /* output: False True False True False True */
연산자 우선 순위
- 포인터 관련 연산자의 우선 순위는 아래 순서를 따르며 괄호
()
를 이용해 우선 순위를 변경할 수 있다.X++
,X--
,->
,[]
++X
,--X
,&
,*
+
,-
>
,<
,>=
,<=
==
,!=