컴퓨터 언어/C

[C] C언어 7일차 포인터2

훈츠 2020. 3. 16. 21:20
반응형

안녕하세요. 훈츠 입니다. 포인터 정복을 해보려고 합니다. 천천히 보시죠.

포인터의 종류와 의미 

  • 포인터        (*****) , 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

 

[C] C언어 6일차 포인터

안녕하세요. 훈츠 입니다. 이번 시간에는 포인터에 대해 정리 해보려고 합니다. 어렵게 느껴졌는데 차근차근 정리 해보니 정리가 되네요. 같이 한번 보시죠. 포인터 메모리 에서 데이터를 읽어오는 방법 메모리..

rain2002kr.tistory.com

이중 포인터 **

  • 역활 : 포인터 변수의 메모리 주소를 저장하는 변수
  • 형식 : 데이터형 **변수명;
    • 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;
}

정리

  • 모든 포인터는 변수이다. 
  • 포인터를 사용하면 메모리를 다양한 방법으로 사용할 수 있다. 
  • 난해한 포인터 사용보다는 직관적인 코드를 사용하는 것이 효율적이다. 
  • 이중 포인터, 함수 포인터, 포인터 배열이 중요하다. 
반응형