오늘은 c언어에서 중요한 역할을 하는 포인터에 대해서 배워보았다. 포인터는 말 그대로 무언가를 가리킨다. 정확하게는 메모리 주소를 저장하기 위한 변수로서 사실 공부하는 중이라 더 쉽게 설명할 수 있는 수준이 아니라 이쯤으로 하고 넘어가 보자.
우리가 코드를 작성할 때 변수를 선언하는 과정은 다음과 같다.
ex) int num1 = 0; // 자료형 변수명 = 값;
이러한 형태에서 참고하여 포인터는 다음과 같이 선언할 수 있다.
자료형* 변수명 = 메모리주소;
간단한 예제를 함께 보면서 이해해 보도록 하자.

다음과 같이 작성했을 때 1번부터 하나씩 보도록 하자 1번은 int 자료형을 반환하는 int자료형 a와 b를 인자로 하는 func함수를 선언하고 있다. 2번은 우리가 앞서 배운 포인터 선언의 형식을 취하고 있지만 뭔가 다르다 *가 자료형 int에도 함수명 pls 붙어있고 뒤에 붙어있거나 앞에 붙어있거나 하는 식으로 다르게 있다 이러한 경우 포인터가 어디를 가리키는지 초심자는 파악하기 상당히 어려워진다. 이에 튜터님은 한 가지 꿀팁을 전수해 줬는데 이는 다음과 같다.

실전을 통해서 이해해 보자
int* (*pls)(void);
1. 변수나 함수명에 해당하는 pls를 읽는다
// pls is
2. 닫히는 괄호 ')'가 있다. 이제 오른쪽에서 왼쪽으로 읽는다 여기서 이미 읽은 pls는 생략한다 그러면 *(Asterisk)가 있다.
// pls is pointer to ~
3. 다시 왼쪽으로 읽다 보면 '('가 닫고 있다. 다시 방향을 바꾸고, 읽은 단어는 생략하서 읽으면 (void)가 있다 이는 함수의 인자에 해당하는 괄호이기에
// pls is pointer to function expecting ~ and returning ~
이고 여기서 인자는 void이기에 해당 함수는 어떠한 인자도 받지 않기에
// pls is pointer to function returning ~ 만 남기면 충분!
4. 이제 다시 ')'를 만나 방향이 바뀌어 읽은 것을 모두 생략하면 *를 먼저 만나고 그 뒤에 int가 있다 그렇기에
//pls is pointer to function returning pointer of int
라는 구문이 완성된다. 이를 해석하면 "pls는 int 자료형을 가리키는 포인터를 반환하는 함수를 가르키는 포인터이다."가 된다 그럼 3번은 어떨까?
int* var [3];
Right - Left 법칙을 이용하면 var is array of pointer to int로서 "var는 int 자료형을 가리키는 포인터의 배열이다." 이번엔 한번 포인터를 선언해 보자 int자료형을 반환하며 인자로 int자료형의 num을 받는 함수 yes의 메모리주소를 저장할 포인터를 선언해 보자.
int* yes(int num);
다시 한번 상기해 보면 포인터는 메모리 주소를 저장한다 즉 저장된 메모리 주소를 꺼내올 방법도 존재해야 한다. c언어에서는 2가지의 방법이 존재한다.
1. 주소 연산자 '&'의 사용
2. 배열의 이름 자체가 그 주소이다.
그리고 주소를 알았으면 그 안의 값을 알아야 할 때가 있다 이럴 때 사용하는 것이 역참조이다. 역참조 연산자 *는 피연산자로 메모리 주소를 받아서 해당 메모리 주소에 저장된 값을 반환한다. 근데 *는 포인터를 선언할 때도, 단순 곱셈을 사용할 때도 사용된다 이를 어떻게 구분할까?
1. 자료형 오른쪽에 붙는다 (ex : int* == 포인터)
2. 피연산자가 한 개(ex : *num == 역참조)
3. 피연산자가 두 개(ex : num1 * num2 == 곱셈)
한번 예제를 확인해 보도록 하자

일단 메인함수에서 int자료형의 num을 100으로 선언, 그 num의 메모리 주소를 저장할 int 자료형의 포인터 pointer_to_int를 선언해 주었다. printf();를 이용하여 각 값을 출력해 줄 건데 다음과 같이 유추해 보았다.
1. printf("num : %d\n", num);
// num : num의 값을 (부호가 없는, 이하생략) 십진법으로 출력 후 줄변환
2. printf("&num : %X\n", &num);
// &num : num의 주소를 16진수 정수, 알파벳 대문자로 출력 후 줄변환
3. printf("&num : %p\n", (void*)&num);
// &num : num의 주소를 void*자료형으로 형변환 후(추후에 배운다) 16진수 8자리로 해석 및 출력 후 줄변환
4. printf("pointer_to_int : %X\n", pointer_to_int);
// pointer_to_int : pointer_to_int에 저장된 메모리 주소를 16진수 정수, 알파벳 대문자로 출력 후 줄변환
5. printf("pointer_to_int : %p\n", (void*)pointer_to_int);
// pointer_to_int : pointer_to_int에 저장된 메모리 주소를 void*로 형변환 후 16진수 8자리로 해석 및 출력 후 줄변환
6. printf("*pointer_to_int : %d\n", *pointer_to_int);
// *pointer_to_int : pointer_to_int를 역참조하여 해당 메모리 주소의 값을 십진수로 출력 후 줄변환
7. printf("*pointer_to_int : %d\n", *(&num)); (올바르진 않지만, 소거하는 식으로 이해를 해보자는 각주가 달려있다.)
// *pointer_to_int : num를 역참조하여 해당 메모리 주소의 값을 십진수로 출력 후 줄변환인데 각주를 신경 쓰고 결과를 보자.
8. printf("(*pointer_to_int)*2 : %d\n", (*pointer_to_int)*2);
// (*pointer_to_int)*2 : pointer_to_int를 역참조하여 해당 메모리 주소의 값의 2배를 십진수로 출력 후 줄변환
한번 값을 출력해 보자.

포인터는 본 듯 시작 주소만으로 큰 데이터드를 공유할 수 있는 장점이 있다 하지만 단점으로 너무나도 쉽게 해당 주소의 값을 수정할 수 있다는 점이 있다. 이는 보안상 상당한 취약점이 될 수 있다 주의해서 쓰도록 하자
'unreal 5기' 카테고리의 다른 글
| 250820 언리얼엔진 본캠프 12일차 STL 기초 (0) | 2025.08.20 |
|---|---|
| 250819 언리얼엔진 본캠프 11일차 포인터 (2) (0) | 2025.08.19 |
| 250814 언리얼엔진 본캠프 9일차 반복문 (4) | 2025.08.14 |
| 250813 언리얼엔진 본캠프 8일차 C언어를 배워보자 (2) (7) | 2025.08.13 |
| 250812 언리얼엔진 본캠프 7일차 C언어를 배워보자 (5) | 2025.08.12 |