반응형
안녕하세요. 훈츠 입니다. 포인터 정복을 해보려고 합니다. 천천히 보시죠.
포인터의 종류와 의미
- 포인터 (*****) , int *pPtr; : int형 메모리 주소를 저장하는 변수 선언
- 포인터 배열 (****) , int*pPtr[3]; : 3개의 열을 가진 배열의 메모리 주소를 저장하는 배열 선언
- void 포인터 (****) , void *pPtr; : 모든 데이터형의 주소를 저장하는 변수 선언
- 사용할때는 반드시 형 변환 (type casting)을 해야 한다.
- 이중 포인터 (**) , int **pPtr; : int *형 메모리 주소를 저장 하는 변수 선언
- 함수 포인터 (**) , (*function)(int) : 함수의 메모리 주소를 저장하는 변수 선언
- 배열 포인터 (*), int (*pPtr)[3]; : 열의 개수가 3개인 int형 이차원 배열의 메모리 주소를 저장하는 변수 선언
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
//포인터 종류별 사이즈 비교
char *pPtr1; //1. 포인터
void* pVoid; //2. void 포인터
char **ppPtr; //3. 이중 포인터
char* pPtrArray[3]; //4. 포인터 배열
char (*func)(int); //5. 함수 포인터
char (*pPtr2)[3]; //6. 배열 포인터
printf("1.포인터:%d\n2.void 포인터:%d\n3.이중 포인터:%d\n4.포인터 배열:%d\n5.함수 포인터:%d\n6.배열 포인터:%d\n",
sizeof(pPtr1), sizeof(pVoid), sizeof(ppPtr), sizeof(pPtrArray), sizeof(func), sizeof(pPtr2));
_getch(); //waiting for step
return 0;
}
포인터 배열 ****
- 역활 : 메모리 주소를 저장하는 배열
- 형식 : 데이터형 *pPtr[열 개수];
- int *pPtr[3]; : int형 메모리 주소 3개를 저장하는 배열 pPtr[0], pPtr[1], pPtr[2]
- (int*)malloc(sizeof(int)*3); : 이렇게 만들어 주고 포인트 배열에 주소값 저장
- 활용 예시
- 임의의 열 길이를 가지는 배열을 연결 할수 있습니다.
- 길이가 다른 문자열을 다룰 때 자주 사용됩니다.
활용예시 1
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
//배열 포인터 예시
int* pPtr[1]; //배열 포인터 선언 : 2개의 int형 포인터를 담을수 있는 포인터
pPtr[0] = (int*)malloc(sizeof(int)*3); //int형포인터 3개 생성
pPtr[1] = (int*)malloc(sizeof(int)*4); //int형포인터 4개 생성
for (int i = 0; i < 3; i++) {
pPtr[0][i] = i; //값넣기 pPtr[0][0] = 1;
printf("ptr[0][%d] , value:%d\n", i, pPtr[0][i]);
}
for (int i = 0; i < 4; i++) {
pPtr[1][i] = i + 4;//값넣기 pPtr[1][0] = 4;
printf("ptr[1][%d], value:%d\n", i, pPtr[1][i]);
}
free(pPtr[0]);
free(pPtr[1]);
_getch(); //waiting for step
return 0;
}
활용 예시2
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
//문자열 배열 포인터 예시2
char* pPtr[3] = { "1.포인터배열 활용1",
"2.포인터배열 활용2",
"3.포인터배열 정리"};
for (int i = 0; i < 3; i++) {
printf("%s\n", pPtr[i]);
}
printf("사이즈 %d", sizeof(pPtr));
_getch(); //waiting for step
return 0;
}
void 포인터 ****
포인터 1탄에 정리해 두었습니다.
https://rain2002kr.tistory.com/150
이중 포인터 **
- 역활 : 포인터 변수의 메모리 주소를 저장하는 변수
- 형식 : 데이터형 **변수명;
- int **pPtr; : int형 변수의 메모리 주소를 가지는 포인터의 포인터 선언
- 포인터 변수의 메모리 주소를 저장.
- 활용 예시
- 변수 <-> 포인터 <-> 이중 포인터
- 포인터 변수의 메모리 주소를 저장
- 열의 개수가 서로 다른 배열을 생성
- **ptr -> [행][열] 개념으로 사용 가능합니다.
- int **ppPtr : 이중 포인터 선언
- ppPtr = (int**)malloc(sizeof(int*)*3); : int형 변수의 주소값을 가지는 3개의 행 생성
- ppPtr[n] = (int*)malloc(sizeof(int)*3); : 만들어진 행에다가 int형 변수의 주소값을 가지는 3개의 열 생성
- free(ppPtr[n]); : 만들어진 행n개를 해제한다.
- free(ppPtr); : 만들어진 **ppPtr 이중 포인터를 해제한다.
활용 예시1
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
//이중 포인터 예시1
int var = 4;
int* pPtr = &var;
int** ppPtr = &pPtr;
printf("주소 %p, %p, %p\n", &var, &pPtr, &ppPtr);
printf("값 %p, %p\n", pPtr, ppPtr);
printf("최종값 %d, %d, %d\n", var, *pPtr, **ppPtr);
_getch(); //waiting for step
return 0;
}
활용 예시2 (포인터 배열 활용과 유사하므로 포인터 배열 활용이 좀더 좋을것 같습니다.)
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
//이중 포인터 예시2
int** ppPtr;
ppPtr = (int**)malloc(sizeof(int*) * 2); //행 2개 생성
ppPtr[0] = (int*)malloc(sizeof(int) * 3); //열 int형포인터 3개 생성
ppPtr[1] = (int*)malloc(sizeof(int) * 4); //열 int형포인터 4개 생성
for (int i = 0; i < 3; i++) {
ppPtr[0][i] = i; //값넣기 ppPtr[0][0] = 1;
printf("pptr[0][%d] , value:%d\n", i, ppPtr[0][i]);
}
for (int i = 0; i < 4; i++) {
ppPtr[1][i] = i + 4;//값넣기 ppPtr[1][0] = 4;
printf("ptr[1][%d], value:%d\n", i, ppPtr[1][i]);
}
//반드시 malloc 으로 만든부분 해제
free(ppPtr[0]);
free(ppPtr[1]);
free(ppPtr);
_getch(); //waiting for step
return 0;
}
활용 예시3 (문자열)
int main() {
//문자열 이중 포인터 예시3,
char list1[] = "1. 이중 포인터 활용1";
char list2[] = "2. 이중 포인터 활용2";
char list3[] = "3. 이중 포인터 활용3";
char** pPtr;
pPtr = (char**)malloc(sizeof(char*) * 4);
pPtr[0] = list1;
pPtr[1] = list2;
pPtr[2] = list3;
for (int i = 0; i < 3; i++) {
printf("%s\n", pPtr[i]);
}
printf("사이즈 %d", sizeof(pPtr));
free(pPtr);
_getch(); //waiting for step
return 0;
}
- 해제시 malloc 으로 만든 데이터 영역만 해제한다.
- 이중 포인터를 이용해 string 값을 지정하는것보다 포인트 배열을 이용하는게 좋을듯합니다.
함수 포인터 ** (추후 콜백함수, 델리게이트, 이벤트에 근원이 되는 함수 포인터)
- 역활 : 함수의 메모리 주소를 저장하고 호출하는 역활
- 형식 : 리턴 데이터형 (*함수 포인터명)(매개변수)
- int (*pFunc)(int, int);
- 활용 예시
- 함수명 역시 주소값을 가지고 있습니다.
- 주소값을 받는 함수 포인터를 활용
- int Add(int var1, int var2) { return var1 + var2; }
- int (*pFunc)(int, int)
- pFunc = Add;
- int result = pFunc(1,2);
활용 예시1
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int Add(int var1, int var2) {
return var1 + var2;
}
int main() {
int (*func)(int, int);
printf("result %d", func = Add(3, 4));
_getch();
return 0;
}
배열 포인터 *
사용 빈도가 낮아서 이런게 있다는 정도만 보면됩니다.
- 역활
- 열의 개수가 같은 이차원 배열의 메모리 주소를 저장하는 역활
- 열의 개수가 고정된 임의의 행을 생성하여 다룰 수 있다.
- 형식 : 3개의열을가지는경우
- 데이터형 (*변수명)[열의 개수];
- int (*pPtr)[3];
- 활용 예시
- 이차원 배열의 메모리 주소를 저장
- 이차원 배열을 함수의 매개변수로 전달할때
- 열의 개수가 고정인 임의의 행을 다룰때
활용 예시
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
int nArray[2][3] = { {10,20,30},{100,200,300} };
int(*pPtr)[3];
pPtr = nArray;
for (int i = 0; i < 2; i++) {
printf("%d %d %d\n", pPtr[i][0], pPtr[i][1], pPtr[i][2]);
}
_getch();
return 0;
}
활용 예시2 (이차원 배열을 매개 변수로 전달할때)
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
void Add(int(*pPtr)[3], int nCnt) {
int i, j;
for (i = 0; i < nCnt; i++) {
for (j = 0; j < 3; j++) {
++pPtr[i][j];
}
}
}
int main() {
int nArray[2][3] = { {10,20,30},{100,200,300} };
int(*pPtr)[3];
pPtr = nArray;
for (int i = 0; i < 2; i++) {
printf("%d %d %d\n", pPtr[i][0], pPtr[i][1], pPtr[i][2]);
}
Add(pPtr, 2);
for (int i = 0; i < 2; i++) {
printf("%d %d %d\n", pPtr[i][0], pPtr[i][1], pPtr[i][2]);
}
_getch();
return 0;
}
활용 예시3 (열의 개수가 고정인 임의의 행을 생성)
#include <stdio.h>
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
int main() {
int(*pPtr)[3];
printf("%d \n", sizeof(pPtr));
pPtr = (int(*)[3])malloc(sizeof(int[3]) * 3);
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
if (i == 1) {
pPtr[i][j] = j + 2;
}
else {
pPtr[i][j] = j ;
}
printf("%d \n", pPtr[i][j]);
}
}
free(pPtr);
_getch();
return 0;
}
정리
- 모든 포인터는 변수이다.
- 포인터를 사용하면 메모리를 다양한 방법으로 사용할 수 있다.
- 난해한 포인터 사용보다는 직관적인 코드를 사용하는 것이 효율적이다.
- 이중 포인터, 함수 포인터, 포인터 배열이 중요하다.
'컴퓨터 언어 > C' 카테고리의 다른 글
[C] C언어 8일차 기타 문법1 (enum, goto, label, union, 전처리기 지시문) (0) | 2020.03.17 |
---|---|
[C] C언어 7일차 구조체와 TypeDef (0) | 2020.03.16 |
[C] C언어 6일차 포인터 (0) | 2020.03.15 |
[C] C언어 5일차 배열 (0) | 2020.03.14 |
[C] C언어 4일차 함수 (0) | 2020.03.13 |