포인터(pointer)란 메모리 주소를 저장하는 변수입니다. 즉, 포인터는 값 대신 메모리 주소를 저장하고, 이를 통해 해당 주소에 접근하여 값에 접근하거나 값을 변경할 수 있습니다.
포인터 변수는 다음과 같은 형태로 선언합니다.
데이터형 *포인터변수명;
이 때, 데이터형은 포인터 변수가 가리키는 메모리 공간에 저장되는 데이터의 자료형입니다. 예를 들어, int형 변수를 가리키는 포인터 변수를 선언할 경우, 다음과 같이 선언합니다.
int *p;
포인터 변수를 선언한 후, 해당 변수에는 & 연산자를 이용하여 다른 변수의 메모리 주소를 대입할 수 있습니다.
int a = 10;
int *p;
p = &a;
위 코드에서 &a는 변수 a의 메모리 주소를 의미하며, p = &a는 p가 a의 메모리 주소를 가리키도록 합니다.
포인터 변수를 이용하여 해당 주소에 저장된 값에 접근할 때는 * 연산자를 이용합니다.
int a = 10;
int *p;
p = &a;
printf("%d", *p); // 출력 결과: 10
위 코드에서 p는 p가 가리키는 메모리 공간에 저장된 값을 의미하며, 위 예시에서 p는 10을 출력합니다.
또한, 포인터 연산을 통해 해당 주소에서 정해진 크기만큼 이동하며 값을 가져올 수도 있습니다. 이를 포인터 산술 연산(pointer arithmetic)이라고 합니다.
포인터는 배열과도 밀접한 관련이 있습니다. 배열 이름은 해당 배열의 첫 번째 요소의 주소를 가리키는 포인터 상수입니다. 따라서, 배열 요소에 접근할 때는 다음과 같이 배열 이름 대신 포인터 변수를 이용할 수 있습니다.
int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;
printf("%d", *(p+2)); // 출력 결과: 3
위 코드에서 *(p+2)는 arr[2]와 동일한 값을 출력합니다.
이중 포인터는 다른 포인터 변수의 주소를 저장하는 포인터입니다. 즉, 포인터를 가리키는 포인터라고 생각할 수 있습니다.
일반 포인터가 변수의 주소를 저장하고 그 변수의 값에 접근하는 것과 마찬가지로 이중 포인터도 다른 포인터 변수의 주소를 저장하고 그 포인터 변수가 가리키는 값을 가져올 수 있습니다.
이중 포인터를 사용하는 이유는 메모리에 대한 직접적인 접근이 가능하다는 것입니다. 이중 포인터를 사용하여 메모리를 동적으로 할당할 수 있으며, 이를 통해 프로그램이 실행 중에 메모리를 할당하고 해제할 수 있습니다.
이중 포인터는 주로 함수에서 포인터를 변경하고자 할 때 사용됩니다. 예를 들어, 함수의 인수로 포인터를 전달할 때, 그 포인터를 변경하여 호출자에게 영향을 미치고자 할 때 이중 포인터를 사용합니다. 또한, 이중 포인터는 포인터 배열과 연관된 작업에서도 사용됩니다.
아래는 이중 포인터를 사용하여 포인터 변수의 값을 변경하는 예시 코드입니다.
#include <stdio.h>
void change_value(int **ptr) {
**ptr = 5; // 포인터 변수가 가리키는 변수의 값 변경
}
int main() {
int num = 10;
int *ptr = # // 포인터 변수 선언 및 초기화
int **dptr = &ptr; // 이중 포인터 선언 및 초기화
printf("%d\n", num); // 10 출력
change_value(dptr); // 포인터 변수의 값 변경
printf("%d\n", num); // 5 출력
return 0;
}
위 코드에서 change_value() 함수는 이중 포인터 ptr을 매개변수로 받아, 해당 포인터가 가리키는 포인터 변수가 가리키는 변수의 값을 변경하는 역할을 한다. 따라서, dptr이 가리키는 포인터 변수 ptr이 가리키는 변수 num의 값이 5로 변경됩니다.
C 언어에서 포인터는 매우 강력한 기능을 제공하며, 프로그램에서 데이터를 효율적으로 처리할 수 있도록 도와주는 핵심적인 개념입니다. 따라서 포인터는 C 언어를 이용한 프로그래밍에서 중요한 역할을 합니다. 이를 표현하기 위해 "C 언어에서 포인터는 꽃"이라는 표현이 사용되곤 합니다.
포인터는 C언어에서 가장 중요하면서도 어려운 개념 중 하나라고 생각합니다. 처음에는 이해하기 어려웠지만, 조금씩 연습하면서 조금씩 감을 잡아갔습니다.
포인터의 가장 큰 장점은 메모리에 직접 접근할 수 있다는 것입니다. 이를 통해 다양한 자료형을 메모리에서 직접 읽고 쓰는 것이 가능해집니다. 그리고 동적 할당을 통해 메모리를 효율적으로 관리할 수 있게 됩니다.
하지만 포인터를 잘못 사용하면 프로그램이 크래시가 발생하거나 메모리 누수 등의 문제가 발생할 수 있기 때문에, 조심스럽게 다뤄야 합니다.
포인터는 어렵기는 하지만, 한 번 제대로 이해하고 익숙해지면 매우 강력한 도구가 될 수 있습니다. 따라서 꾸준한 연습과 응용 능력을 키우는 것이 중요하다고 생각합니다.