본문 바로가기

C Programming

포인터

포인터 연산



  • 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 **임.