728x90
반응형

< 포인터 이해하기 >

 

> 포인터 (pointer) 의 개념

1) 포인터란?

(1) 메모리의 주소값 (일반적으로 16진수 값으로 표현)

- 포인터 변수 : 포인터를 값으로 가질 수 있는 변수

 

2) 포인터 변수 선언

(1) 포인터 변수 선언 시 변수 이름 앞에 *를 붙여서 선언

자료형 *변수명;

- 자료형 지정 포인터 변수

: 지정된 자료형의 메모리 주소값만 저장

int *a;
float *b;
char *c;

 

-자료형 미지정 포인터 변수

: 모든 자료형의 메모리 주소값을 저장

: 자료형 대신에 void 사용

void *d;

 

3) 포인터 변수 초기화

(1) 일반 변수의 메모리 주소값 지정

- 주소 참조 연산자(&)를 일반변수 이름 앞에 붙여서 사용

(2) 메모리 주소값 0을 의미하는 NULL 지정

int a = 1;

int *p = &a;
int *p;
p = &a;

int *p = NULL;
p = &a;

* 포인터 변수 선언과 별도로 초기값 지정 권장

 

 

 

> 포인터 변수 사용하기

1) 포인터 변수에 입력하기

- scanf_s() 함수 사용시 주소 참조 연산자(&) 사용하지 않음

int a;
scanf_s("%d", &a);

int *p = &a;
scanf_s("%d", p);

 

2) 포인터 변수 출력하기

- 간접 참조 연산자( * ) 를 이용

: 포인터 변수 이름 앞에 붙여서 사용

: 포인터 변수가 가리키는 메모리에 저장되어 있는 값을 의미

int a = 10;
int *p = &a;
printf("%d", *p);	// 간접참조연산자 (*) 가 없을 경우 주소값 0x123 이 출력

 

3) 포인터 연산하기

(1) 포인터의 연산

- 정수값을 이용한 덧셈과 뺄셈 연산만 가능

- 동일한 자료형 포인터끼리 대입 연산 가능

 

- 포인터 관련 연산자 우선순위

우선순위 종류 연산자
1 증감연산자 ++, --
2 주소 참조 연산자
간접 참조 연산자
&
*
3 산술 연산자 +, -
4 비교 연산자 ==, !=
5 대입 연산자 =, +=, -=

 

(2) 포인터 증감 연산

- 메모리 주소값의 증감 연산

- 자료형의 크기 만큼 증감

자료형 연산 설명
char *p p++, p+1 포인터 값 1 증가
p--, p-1 포인터 값 1 감소
int *p p++, p+1 포인터 값 4 증가
p--, p-1 포인터 값 4 감소
double *p p++, p+1 포인터 값 8 증가
p--, p-1 포인터 값 8 감소

 

4) void 포인터 변수

(1) void 포인터 변수의 개요

- 포인터 변수의 자료형을 미지정

- 모든 자료형의 포인터를 지정할 수 있음

 

(2) void 포인터 변수의 값 출력

- void 포인터 변수에 지정된 자료형으로 형 변환 필요

int a = 10;
char b = 'A';

void *p = NULL;	// void 포인터 변수 선언 및 초기화

p = &a;	// int형 포인터 지정
p = &b;	// char형 포인터 지정

printf("%d", *(int*)p);	// void형 포인터 변수를 int형 포인터변수로 형 변환
printf("%d", *(char*)p);	// void 형 포인터 변수를 char형 포인터 변수로 형 변환

 

5) 이중 포인터

(1) 이중 포인터 변수의 개요

- 포인터 변수의 포인터를 저장하는 변수

- 변수 이름 앞에 ** 를 붙여서 선언

 

(2) 이중 포인터 변수 출력

- 변수 이름 앞에 ** 를 붙여서 사용

int a = 10;
int *p = &a;
int **PP = &p;

printf("%d", a);	// 10
printf("%d", *p);	// 10
printf("%d", **pp);	// 10

 

 

> 포인터 기본 실습

#include <stdio.h>

int main(void)
{
	// 포인터 변수 선언
	int* a;
	float* b;
	char* c;
	void* d;

	// 포인터 변수 초기화
	int a1 = 10;
	int* p = &a1;	// 포인터 변수 선언과 동시에 초기화

	int a2 = 10;
	int* p2;	// 포인터 변수 선언시 초기화 하지 않음
	p2 = &a2;

	int a3 = 10;
	int* p3 = NULL;	// NULL로 초기화
	p3 = &a3;

	// 포인터 변수 입출력
	int a4 = 0;
	int* p4 = NULL;
	p4 = &a4;

	printf("값을 입력하시오 : ");
	scanf_s("%d", p4);
	printf("p4 변수가 가리키는 메모리의 값은 %d 입니다.\n", *p4);
	printf("p4 변수의 값은 %p 입니다.\n", p4);
	printf("a4 변수의 값은 %d 입니다.\n\n", a4);

	// 포인터 연산
	int a5 = 100;
	int* p5 = &a5;
	printf("p5 변수의 값은 %p\n", p5);
	printf("p5 변수가 가리키는 메모리의 값은 %d\n", *p5);

	p5 = p5 + 1;	// p5 ++ 와 동일, int 형이므로 4 증가
	printf("p5 변수의 값은 %p\n", p5);
	printf("p5 + 1 변수가 가리키는 메모리의 값은 %d\n", *p5);	// 쓰레기값 저장

	p5 = p5 - 1;	// p5 -- 와 동일, int 형이므로 4 감소
	printf("p5 변수의 값은 %p\n", p5);
	printf("p5 - 1 변수가 가리키는 메모리의 값은 %d\n", *p5);

	a5 = *p5 + 1;
	printf("p5 변수가 가리키는 값은 %d, a5 변수의 값은 %d\n\n", *p5, a5);

	// 연산자 우선순위
	int a6 = 100;
	int* p6 = &a6;
	printf("p6 변수의 값은 %p, a6 변수의 값은 %d\n", p6, a6);
	int a7 = *p6++;	// a7 = *p6, p6++ 와 동일(후위연산)
	printf("p6 변수의 값은 %p, a7 변수의 값은 %d\n", p6, a7);

	p6 = &a6;
	a6 = (*p6)++;
	printf("p6 변수가 가리키는 값은 %p, a6 변수의 값은 %d\n", p6, a6);

	p6 = &a6;
	a6 = *p6++ + 1;	// a6 = *p6 + 1, p6 ++ 와 동일
	printf("p6 변수가 가리키는 값은 %p, a6 변수의 값은 %d\n", p6, a6);

	p6--;	// *p-- 와 동일
	printf("p6 변수가 가리키는 값은 %p, a6 변수의 값은 %d\n", p6, a6);

	// void 포인터 변수
	void* vp = NULL;
	int va = 100;
	char vb = 'A';

	vp = &va;
	printf("vp 변수의 값은 %p, vp 변수가 가리키는 값은 %d\n", vp, *(int*)vp);

	vp = &vb;
	printf("vp 변수의 값은 %p, vp 변수가 가리키는 값은 %c\n", vp, *(char*)vp);

	// 이중 포인터 변수
	int a8 = 10;
	int* p8 = &a8;
	int** pp8 = &p8;
	printf("a 변수의 값은 %d\n", a8);
	printf("*p 변수의 값은 %d\n", *p8);
	printf("**p 변수의 값은 %d", **pp8);

	return 0;
}

 


< 배열과 포인터의 관계 이해하기 >

 

> 배열과 포인터의 관계

1) 일차원 배열과 포인터의 관계

(1) 배열 이름은 포인터 변수임

(2) 배열의 각 요소는 메모리에 연속해서 저장됨

(3) 배열의 각 요소는 포인터 변수로 표현할 수 있음

int a[5] = { 1, 2, 3, 4, 5 };

int* p = a;	// 배열의 이름은 포인터변수임, & 사용안함

 

2) 이차원 배열과 포인터의 관계

(1) 배열 이름과 행을 대표하는 변수 이름은 포인터 변수임

(2) 배열의 각 요소는 메모리에 연속해서 저장됨

(3) 배열의 각 요소는 포인터 변수로 표현할 수 있음

(4) 배열 포인터를 이용하여 배열처럼 사용하기

#include <stdio.h>

int main(void)
{
	int a[3][4] =
	{
		{1, 2, 3, 4},
		{5, 6, 7, 8},
		{9, 10, 11, 12}
	};

	int* p = a, * p0 = a[0], * p1 = a[1], * p2 = a[2];
    
    // 이차원 배열의 시작주소
    int (*p)[4] = a;

	return 0;
}

 

 

> 포인터 배열 이해하기

1) 포인터 배열 개요

(1) 포인터가 배열의 요소인 배열

(2) 배열의 요소가 포인터임

 

2) 포인터 배열 선언

- 배열 이름 앞에 * 를 붙여서 선언

자료형 *배열이름[배열크기];
int* p1
int* p2
int* p3
int* p4
int* p5

→ int *p[5]

 

3) 포인터 배열을 이용한 문자열 처리

- 여러 개의 문자열을 하나의 배열로 처리

#include <stdio.h>

int main(void)
{
	char* p1 = "pointer";
	char* p2 = "c programming";

	// 하나의 배열로 처리
	char* p[2] =
	{
		"pointer",
		"c programming"
	};

	printf("%s\n", p[0]);	// pointer
	printf("%s\n", p[1]);	// c programming

	return 0;
}

 

 

> 배열과 포인터 관계 실습

#include <stdio.h>

int main(void)
{
	// 1차원 배열
	printf("1차원 배열 출력\n");
	int a1[5] = { 1, 2, 3, 4, 5 };
	for (int i = 0; i < 5; i++)
	{
		printf("%3d", a1[i]);
	}

	printf("\n1차원 배열 출력(포인터 이용)\n");
	int a2[5] = { 1, 2, 3, 4, 5 };
	int* p2 = a2;	// 배열 포인터 변수: 배열을 가리키는 포인터 변수
	for (int i = 0; i < 5; i++)
	{
		printf("%3d", *(p2 + i));
		//printf("%3d", p2[i]);
		//printf("%3d", p2++);	// 차이점 p2 변수의 주소값이 변동됨
	}

	// 2차원 배열
	printf("\n2차원 배열 출력\n");
	int a3[3][4] =
	{
		{1, 2, 3, 4},
		{5, 6, 7, 8},
		{9, 10, 11, 12}
	};
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("%3d", a3[i][j]);
		}
		printf("\n");
	}

	printf("2차원 배열 출력(포인터 이용)\n");
	int a4[3][4] =
	{
		{1, 2, 3, 4},
		{5, 6, 7, 8},
		{9, 10, 11, 12}
	};
	int* p4 = a4;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("%3d", *(p4 + (i * 4) + j));
			//printf("%3d", p4[i][j]);	// 포인터 배열 사용해야 함
			//printf("%3d", *p4++);
		}
		printf("\n");
	}

	printf("2차원 배열 출력(각 행의 포인터 이용)\n");
	int a5[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} };
	int* p5 = a5, * p_0 = a5[0], * p_1 = a5[1], * p_2 = a5[2];

	for (int i = 0; i < 4; i++)
	{
		printf("%3d", *(p_0 + i));
	}
	printf("\n");
	
	for (int i = 0; i < 4; i++)
	{
		printf("%3d", *(p_1 + i));
	}
	printf("\n");

	for (int i = 0; i < 4; i++)
	{
		printf("%3d", *(p_2 + i));
	}

	printf("\n2차원 배열 출력(배열 포인터 이용)\n");
	int(*pa)[4] = a5;
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("%3d", pa[i][j]);
		}
		printf("\n");
	}

	// 문자열 포인터 배열 : 포인터를 배열로 가지는 것
	printf("문자열 포인터 배열\n");
	char* p6[2] = { "pointer", "c programming" };
	for (int i = 0; i < 2; i++)
	{
		printf("%s\n", p6[i]);
	}

	return 0;
}
728x90
반응형

'Language > C & C++' 카테고리의 다른 글

C_10. Basic Grammar of Structure  (0) 2022.08.15
C_09. Basic Grammar of Function  (0) 2022.08.12
C_07. Basic Grammar of Array  (0) 2022.08.11
C_06. Basic Grammar of Iteration Statement  (0) 2022.08.10
C_05. Basic Grammar of Conditional Statement  (0) 2022.08.10

+ Recent posts