34~35. 핵심 정리
포인터와 메모리
포인터
- 포인터는 메모리의 특정 위치를 가리킬 때 사용하며, 정수형으로 된 메모리 주소가 저장되어 있다.
- 포인터는
*
(애스터리스크)를 사용하여 선언한다. - 이미 선언된 포인터에
*
(역참조 연산자)를 사용하면 포인터에 저장된 메모리 주소에 접근(역참조)하여 값을 가져오거나 저장할 수 있다.
자료형 * 포인터이름; // 포인터 선언 (
[포인터와 포인터 역참조]*
의 위치는 자료형 쪽, 포인터 쪽, 중간 어디든 무관)
* 포인터; // 포인터를 역참조하여 값을 가져옴
* 포인터 = 값; // 포인터를 역참조하여 값을 저장
변수의 메모리 주소
- 변수의 메모리 주소를 구할 때는
주소 연산자 &
를 사용한다. &
로 구한 주호는 포인터에 할당할 수 있다.- 즉, 포인터와 변수의 메모리 주소는 자료형이 같다. ⭐
포인터 = &변수; // 변수의 메모리 주소를 포인터에 저장
포인터, 역참조 연산자(*), 주소 연산자(&)의 관계
포인터와 주소의 자료형
int * a;
는 ponter to int라고 읽으며,*a
와 같이 변수를 역참조하면 pointer to를 제거하여 int로 만든다.int b;
에서&b
와 같이 변수의 주소를 구한 것을 address of int라고 읽는다. address of int는 pointer to int와 자표형이 같으므로 포인터에 주소를 할당할 수 있다.- 포인터와 주노는 표기법만 차이가 있을 뿐 본질은 같다.
포인터의 자료형과 역참조
포인터는 포인터를 선언한 자료형의 크기만틈 역참조하는 크기가 결전된다.
char *cPtr1; // char형 포인터 선언
*cPtr1 = 'a'; // char의 크기 1바이트만큼 역참조하여 값을 저장
short *numPtr1; // short형 포인터 선언
*numPtr1 = 100; // short의 크기 2바이트만큼 역참조하여 값을 저장
int *numPtr2; // int형 포인터 선언
*numPtr2 = 100; // int의 크기 4바이트만큼 역참조하여 값을 저장
long long *numPtr3; // long long형 포인터 선언
*numPtr3 = 100; // long long의 크기 8바이트만큼 역참조하여 값을 저장
void 포인터
- void 포인터는 어떤 자료형으로 된 포인터든 모두 저장할 수 있다.
- 반대로 다양한 자료형으로 된 포인터에도 void 포인터를 저장할 수 있다.
- 이러한 특성 때문에 void 포인터는 범용 포인터라고 한다.
- 단, 자료형의 크기가 정해지지 않았기 때문에 역참조 할 수 없다.
이중 포인터
- 포인터도 일반 변수이므로 다른 포인터의 메모리 주소를 저장할 수 있다.
- 포인터의 메모리 주소를 담고 있ㄴ느 포인터를 이중 포인터라고 한다.
- 이중 포인털르 선언할 때는
*
를 두 개 사용하며, 역참조할 때도*
를 두 개 사용한다. int **a;
는 ponter to pointer to int이다.
자료형 ** 포인터이름; // 이중 포인터 선언
**포인터; // 이중 포인터를 역참조하여 값을 가져옴
**포인터 = 값; // 이중 포인터를 역참조하여 값을 저장
메모리
메모리 할당하기
mallco 함수
를 사용하면 메모리를 바이트 단위로 할당할 수 있다.- malloc 함수는 힙(heap) 부분의 메모리를 사용하며, 일반 변수와 다르게 메모리 사용 후 반드시 해제를 해주어야 한다.
free 함수
로 메모리를 해제할 수 있다.- 메모리를 해제하지 않으면 메모리 누수현상이 발생할 수 있다.
자료형 *포인터이름 = malloc(크기); // 일정 크기만큼 동적 메모리 할당
free(포인터); // 동적 메모리 해제
메모리를 특정 값으로 설정하기
memset
함수를 사용하면 메모리의 내용을 한꺼번에 특정 값으로 설정할 수 있다.- 값을 설정하는 단위는 바이트 단위이다.
- 주로 메모리 값을 0으로 초기화 할 때 사용한다.
memset(포인터, 설정값, 크기);
널 포인터
- 포인터가 아무것도 가리키고 있지 않는 상태를 __널 포인터(null pointer)라 한다.
- 포인터에 HULL을 할당하면 된다.
자료형 * 포인터이름 = NULL; // 포인터에 HULL 할당
잘못된 포인터 사용
- 포인터에 임의의 값을 할당하면 안된다.
- ⭐ 반드시 이미 있는 변수의 메모리 주소를 구해서 할당하거나, mallco 함수로 메모리를 할당해야 한다.
int *numPtr = 0x100; // 잘못된 포인터 사용, 임의의 값을 할당하면 안 됨
int num1;
int *numPtr = &num1; // 변수 num1의 메모리 주소를 포인터 변수에 저장
int *numPtr = malloc(sizeof(int)); // int의 크기만큼 동적 메모리 할당
Q&A
효율적인 메모리 할당 크기는?
오래 전의 컴퓨터나 일부 임베디드 시스템 등 메모리 크기가 작은 플랫폼은 2의 배수 크기를 권장했다. 하지만 지금은 메모리 크기가 커졌고, 운영체제에서 다양한 알고리즘을 사용하여 메모리를 효율적으로 관리해주므로 이 부분은 크게 신경쓰지 않아도 된다. 메모리를 할당한 뒤 해제를 철저히 해주는 것만으로도 충분하다.
malloc 함수에 음수를 지정하면?
그냥 NULL이 반환된다. malloc 함수는 양수만 사용해야 하낟.
const 포인터를 읽는 방법은?
포인터는 무조건 역순으로 읽으면 쉽다.
- int *: pointer to int
- int const *: pointer to const int
- int * const: const pointer to int
- int const * const: const pointer to const int
- int ** const: const pointer to pointer to int
- int * const * const: const pointer to const pointer to int
const ponter는 포인터의 주소가 바뀌지 않는다는 의미
const int는 int 변수의 값이 바뀌지 않는다는 의미
두 포인터가 같다는 것은 어떤 의미?
포인터에 저장된 것은 메모리 주소이다. 메모리 주소도 정수이므로 두 포인터를 비교할 수 있다.
int *ptr1;
int *ptr2;
// 생략 ...
if (ptr1 == ptr2) { ... } // 포인터는 ==로 비교할 수 있음
두 포인터가 서로 같다면 메모리 주소가 같다는 뜻이다.
같은 메모리 공간을 가리키게 되므로 두 포인터를 역참조했을 때의 값도 서로 같다
메모리 주소가 아닌 값을 바로 비교하고 싶다면 포인터를 역참조한 뒤 비교하면 된다.
int *ptr1;
int *ptr2;
// 생략 ...
if (*ptr1 == *ptr2) { ... } // 포인터를 역참조하여 ==로 비교
쓰레기 값이란?
변수, 배열을 선언하거나 메모리를 할당하면 사용이 끝난 메모리를 다시 사용하게 된다. 쓰레기 값은 이전에 메모리를 사용할 때 저장된 값을 뜻하며, 메모리를 다시 사용하는 시점에서는 필요없는 값이므로 쓰레기 값이라 부른다. 따라서 변수, 배열을 선언하거나 메모리를 사용할 때 쓰레기 값이 다시 사용되자 않도록 내용을 초기화해야 한다.
출처
https://dojang.io/mod/page/view.php?id=605
https://dojang.io/mod/page/view.php?id=606
Author And Source
이 문제에 관하여(34~35. 핵심 정리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@shuajjjjj/3435.-핵심-정리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)