< 포인터 이해하기 >
> 포인터 (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;
}
'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 |