티스토리 뷰
포인터는 메모리 주소를 저장하는 변수입니다. 일반적인 변수는 데이터를 직접 저장하지만, 포인터는 다른 변수나 데이터가 저장된 메모리 주소를 저장합니다. 포인터는 C 언어에서 매우 중요한 개념으로, 메모리 관리, 함수의 인자 전달, 동적 메모리 할당 등을 수행할 때 자주 사용됩니다.
포인터의 기본 개념
1. 포인터 선언
포인터는 메모리 주소를 저장하기 위한 변수입니다. 선언할 때는 변수가 가리킬 데이터 타입을 지정해야 하며, 변수 이름 앞에 *를 붙여 포인터임을 표시합니다.
int* ptr;
- 여기서 ptr은 int형 데이터를 가리키는 포인터입니다. 즉, ptr은 어떤 int형 변수가 저장된 메모리 주소를 저장할 수 있습니다.
2. 포인터에 값을 할당 (주소 대입)
포인터 변수는 다른 변수의 메모리 주소를 저장합니다. 주소를 구하려면 변수 이름 앞에 주소 연산자(&)를 붙입니다.
int num = 10;
int* ptr = # // num의 주소를 ptr에 저장
- num이라는 변수의 값은 10이고, ptr은 num이 저장된 메모리 주소를 가리킵니다.
3. 포인터를 통한 값 참조 (역참조)
포인터를 사용해 가리키고 있는 변수의 값을 가져오려면, 역참조 연산자(*)를 사용합니다.
int num = 10;
int* ptr = #
printf("%d\n", *ptr); // ptr이 가리키는 num의 값을 출력 (10)
- *ptr은 ptr이 가리키고 있는 변수(num)의 값을 참조합니다. 이때 *ptr은 num의 값인 10을 의미합니다.
4. 포인터 연산
포인터는 메모리 주소를 가리키기 때문에 연산을 통해 가리키는 주소를 변경할 수 있습니다. 포인터에 숫자를 더하거나 빼면, 해당 자료형의 크기만큼 메모리 주소가 이동합니다.
int arr[3] = {10, 20, 30};
int* ptr = arr; // 배열의 첫 번째 요소를 가리킴
printf("%d\n", *ptr); // 출력: 10 (arr[0])
ptr++; // 포인터를 다음 요소로 이동
printf("%d\n", *ptr); // 출력: 20 (arr[1])
- ptr++은 포인터를 배열의 다음 요소로 이동시키는 연산입니다. 포인터가 int형일 때는 4바이트(32비트 시스템 기준)씩 이동합니다.
포인터의 활용
1. 함수에서 포인터 사용
포인터는 함수 인자 전달 시 매우 유용하게 사용됩니다. C 언어에서 함수는 기본적으로 값에 의한 복사로 인자를 전달하므로, 함수 내부에서 인자의 값을 변경해도 원본 값에는 영향을 미치지 않습니다. 하지만 포인터를 사용하면 원본 데이터에 접근해 직접 값을 변경할 수 있습니다.
void changeValue(int* ptr) {
*ptr = 100; // ptr이 가리키는 값을 변경
}
int main() {
int num = 10;
changeValue(&num); // num의 주소를 전달
printf("%d\n", num); // 출력: 100 (num의 값이 변경됨)
}
- changeValue 함수는 포인터를 통해 num의 주소를 받아, num의 값을 직접 변경할 수 있습니다.
2. 배열과 포인터
배열 이름은 포인터처럼 배열의 첫 번째 요소의 주소를 가리킵니다. 따라서 배열과 포인터는 밀접한 관련이 있으며, 배열을 다룰 때 포인터를 자주 사용합니다.
int arr[3] = {1, 2, 3};
int* ptr = arr; // 배열 이름은 첫 번째 요소의 주소
printf("%d\n", *ptr); // 출력: 1 (arr[0])
printf("%d\n", *(ptr+1)); // 출력: 2 (arr[1])
- arr는 배열의 첫 번째 요소를 가리키며, ptr도 같은 주소를 가리킵니다. 따라서 포인터 연산을 통해 배열의 각 요소에 접근할 수 있습니다.
3. 동적 메모리 할당
포인터는 동적 메모리 할당에서 필수적으로 사용됩니다. malloc, calloc, realloc 등을 사용해 동적으로 메모리를 할당하면, 이 메모리의 주소를 포인터가 저장하여 나중에 사용할 수 있습니다.
int* ptr = (int*)malloc(sizeof(int) * 5); // int형 5개를 저장할 메모리 할당
ptr[0] = 1;
ptr[1] = 2;
free(ptr); // 메모리 해제
- malloc은 메모리를 할당하고, 그 메모리의 시작 주소를 포인터로 반환합니다. 할당한 메모리를 다 사용한 후에는 반드시 free를 사용해 메모리를 해제해야 합니다.
포인터의 종류
1. 널 포인터 (NULL Pointer)
- 널 포인터는 가리키는 대상이 없는 포인터로, 일반적으로 초기화되지 않은 포인터는 NULL로 설정합니다.
int* ptr = NULL;
- NULL 포인터를 역참조하려 하면 프로그램이 충돌하거나 오류가 발생할 수 있습니다.
2. 이중 포인터 (Pointer to Pointer)
- 이중 포인터는 포인터를 가리키는 포인터입니다. 즉, 이중 포인터는 포인터의 주소를 저장합니다.
int num = 10;
int* ptr = #
int** pptr = &ptr;
printf("%d\n", **pptr); // 출력: 10 (num의 값)
- pptr는 ptr의 주소를 가리키고, *pptr은 ptr을 역참조합니다. **pptr은 최종적으로 num의 값을 가리킵니다.
포인터의 장점과 주의사항
장점:
- 메모리 직접 제어: 포인터를 통해 메모리 주소를 직접 조작할 수 있습니다.
- 효율적인 함수 호출: 포인터를 사용하면 대용량 데이터를 복사하지 않고, 주소만 전달함으로써 성능을 향상시킬 수 있습니다.
- 동적 메모리 할당: 프로그램 실행 중에 필요한 만큼의 메모리를 동적으로 할당할 수 있습니다.
주의사항:
- 포인터 연산 오류: 잘못된 포인터 연산은 프로그램 충돌이나 예기치 않은 동작을 초래할 수 있습니다.
- 메모리 누수: 동적 메모리 할당 후 메모리를 해제하지 않으면 메모리 누수가 발생할 수 있습니다.
- 널 포인터 참조: 널 포인터를 역참조하려 하면 프로그램이 비정상 종료될 수 있습니다.
요약
- 포인터는 메모리 주소를 저장하는 변수입니다.
- 포인터는 변수의 값을 참조하거나, 함수에 값을 참조 방식으로 전달할 때 유용하게 사용됩니다.
- 배열과 포인터는 밀접하게 연관되어 있으며, 동적 메모리 할당에서도 포인터가 필요합니다.
- 포인터는 매우 강력한 도구이지만, 올바르게 사용하지 않으면 프로그램 오류나 충돌을 일으킬 수 있으므로 주의해야 합니다.
포인터는 C 언어의 중요한 개념 중 하나로, 이를 잘 이해하면 메모리 관리와 최적화된 프로그램 설계가 가능합니다.
'Study > 정보처리기사' 카테고리의 다른 글
토큰과 관련된 용어들 (1) | 2024.10.08 |
---|---|
동적 바인딩(Dynamic Binding)이란? (0) | 2024.10.08 |
비트 이동(Shift) 연산이란? (0) | 2024.10.08 |
추상 팩토리(Abstract Factory) 패턴이란? (0) | 2024.10.07 |
공격 기법 관련 문제 (0) | 2024.10.07 |
- Total
- Today
- Yesterday
- Jest
- x.y.z (메이저.마이너.패치)
- stdlib.h
- math.h
- jackson 라이브러리
- defaultdict
- 쉽게 풀어쓴 C언어 Express
- json.parse(json.stringify())
- structuredclone()
- 중첩 함수(nested function)
- counter
- 소프트웨어 버전 관리
- javascript 필수 문법
- 시맨틱 버전(semantic versioning
- 원시값(primitive)
- ajax (asynchronous javascript and xml)
- useEffect
- react
- chrome extension 자동 배포
- styled-components
- 프로세스 강제 종료
- pwa(progressive web app)
- mermaid-cli
- inp
- react router
- public vs assets
- named export vs default export
- core web vitals
- semver)
- Collections
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |