포인터 연산
- T형 포인터
register변수 외에 변수들은 메모리에 저장되므로 이 변수의 번지를 가리키는 포인터 변수를 항상 선언할 수 있음.
포인터 변수 선언
임의의 타입 T가 있을 때 T형의 포인터 변수를 선언할 수 있음.
ex) int* pNum;
선언시 주의)
int *i, j; // i는 포인터, j는 정수형
int *i, *j; // i와 j 모두 포인터
- 포인터의 타입
포인터가 가리키는 번지에 들어있는 값, 즉 포인터가 가리키는 실체를 대상체(object)라고 함.
컴파일러가 포인터 연산에 대해 대상체의 크기만큼 앞뒤로 이동시킬 수 있으려면 이 포인터가 가리키는 대상체의 타입이 무엇인가를 알아야 함. 그래서 포인터 변수를 선언할 때 가리킬 대상체의 타입을 명시하는 것. 포인터형 변수의 타입은 포인터가 가리키는 대상체에 대한 타입을 명시하여 "정수형 변수에 대한 포인터"식으로 표현해야 하나 간단히 줄여서 "정수형 포인터"라고 칭함.
- 포인터 연산
포인터 연산이란 피연산자 중의 하나가 포인터인 연산임. pi++과 같이 포인터형 변수에 대한 연산, pi1 - pi2같이 포인터끼리의 연산이나 ar-pi, pi+3같이 포인터 변수나 포인터 상수가 피연산자 중에 하나라도 있으면 이런 연산을 포인터 연산이라고 함.
1. 포인터끼리 더할 수 없음(더할 수는 있으나 의미가 없음)
2. 포인터끼리 뺄 수는 있음(배열에서 뺄셈이 의미가 있음)
3. 포인터에 정수를 더하거나 뺄 수 있음(배열에서 이용)
4. 포인터끼리 대입할 수 있음
5. 포인터와 실수와의 연산은 허용되지 않음
6. 포인터에 곱셈이나 나눗셈을 할 수 없음
7. 포인터끼리 비교는 가능(ptr == NULL)
- *ptr++
*ptr++을 연산하려면 2가지의 단계가 필요함.
1. (*ptr)++ : ptr이 가리키는 번지의 값을 나타냄
2. *(ptr++) : ptr주소를 sizeof(ptr)만큼 증가시켜줌(int형 포인터라면 메모리 +4가 됨)
void형 포인터
- void형
포인터형 변수는 선언할 때 반드시 대상체의 타입을 밝혀야 함. 가리키는 대상체의 타입을 알아야 * 연산자로 대상체를 읽을 수 있고 증감 연산자로 전후 이동이 가능함. 이런 일반적인 포인터에 비해 선언할 때 대상체의 타입을 명시하지 않는 특별한 포인터형이 있는데 이것이 바로 void형 포인터임.
void형 포인터 선언
void *vp;
void형은 함수와 포인터 변수에게만 적용되는 타입이므로 일반 변수에는 쓸 수 없음.
void 포인터 특징
1. 임의의 대상체를 가리킬 수 있음(정수형, 실수형 모든 포인터를 가리킬 수 있음)
2. *연산자를 쓸 수 없음(번지값만을 저장할 뿐 사용하려면? "*(int *)vp;" 처럼 이용)
3. 증감 연산자를 쓸 수 없음(얼마만큼 이동해야 할지를 모르기 때문)
- void형 포인터의 활용
포인터로 액세스해야 할 대상체가 분명히 정해져 있을 때는 해당 대상체형의 포인터 변수를 사용하면 됨. 예를 들어 정수형의 ar 배열을 액세스할 때는 정수형 포인터를 사용하고 문자열을 다루고 싶을 때는 문자형 포인터를 씀.
- NULL 포인터
NULL 포인터는 0으로 정의되어 있는 포인터 상수값임. 아주 특수한 시스템에서는 0이 아닐 수도 있지만 일반적으로 0이라고 생각하면 큰 무리가 없음.
동적 메모리 할당
- 할당의 필요성
동작할당이란 프로그램을 작성ㅎ라 때 메모리 필요량을 지정하는 정적 할당과는 달리 실행 중에 필요한 만큼 메모리를 할당하는 기법.
- 메모리 관리 원칙
1. 메모리 관리의 주체는 운영체제
2. 운영체제는 메모리가 있는 한은 할당 요청을 거절하지 않음
3. 한 번 할당된 메모리 공간은 절대로 다른 목적을 위해 재할당되지 않음
4. 응용 프로그램이 할당된 메모리를 해제하면 운영체제는 이 공간을 빈 영역으로 인식하고 다른 목적을 위해 사용할 수 있도록 함
- 할당 및 해제
동적 메모리 할당의 형식
void *malloc(size_t size);
동적 메모리 해제의 형식
void free(void *memblock);
- 재할당
재할당의 형식
void *realloc(void *memblock, size_t size);
이중 포인터
- 이중 포인터
이중 포인터란 포인터 변수를 가리키는 포인터라는 뜻
이중포인터의 예
int **ppi;
- main 함수의 인수
main도 일종의 함수이므로 인수를 가질 수 있고 리턴값도 가질 수 있음.
1. int main(void);
2. int main(int argc, char *argv[]);
- 동적 문자열 배열
배열의 크기를 입력을 받아 선언할 때 크기를 지정할 수 없으므로 동적메모리 할당을 통해 문자열을 선언해주어야 함.
ex)
int len;
scanf("%d", &len);
char *name;
name = (char *)malloc(len *sizeof(char));
// ....생략
free(name);
- void 이중 포인터
ex)
void alloc(void **mem, size_t size)
{
*mem = malloc(size);
}
void main()
{
void *vp;
alloc(&vp, sizeof(int));
*(int *)vp = 1234;
printf("%d\n", *(int *)vp);
free(vp);
}
메모리를 대신 할당하는 함수를 만들고 싶을 때 이 함수가 받아야 할 타입이 바로 void **임.