배열과 포인터 - 2
포인터의 개념, 포인터의 선언과 참조방법, 포인터의 기억공간의 표현, 포인터 연산.
- 학습 목표
- 변수의 주소 이해.
- 표인터 개념 이해.
- 포인터 변수 선언 및 참조.
- 포인터 기억공간 표현의 이해.
- 포인터 연산의 이해.
주요 용어
- 포인터 : 변수의 주소 값을 갖는 특별한 변수.
- void형 포인터 : 프로그램 실행 시에 자료형이 경정되는 경우에 사용되는 포인터.
- 포인터 연산 : 포인터 변수에 +, -, ++, -- 연산자를 사용하는 연산.
포인터(pointer)의 개념
pointer : 변수의 일종.
- 변수 : 특정 데이터 값을 가지고 있음.
- 포인터 : 특정 데이터가 저장된 기억장소의 주소(번지)값을 가지고 있음.
기억공간을 변수명으로 접근하지 않고 주소로 접근하기 위해 사용.
일반적인 변수의 기억공간 표현
- 변수는 변수 선언에 의해 기억공간이 할당됨.
- 할당된 기억공간에 변수에 대입된 데이터가 저장.
- 할당된 기억공간은 주소(번지)가 부여되어 있음.
- -> 변수가 주소를 의미 한다면, 주소를 이용하여 변수와 같은 동일한 작업이 가능하다.
- -> 따라서 주소값(포인터 값)을 다룰 수 있는 변수가 필요.
- -> 포인터 변수 : 변수의 주소 값을 갖는 특별한 변수.
변수 주소의 예
#include <stdio.h>
void main()
{
int days = 365;
int month = 12;
int Table[5] = {1, 2, 3, 4, 5};
// & : 주소를 의미한다.
printf("addr of days : %x\n", &days);
printf("addr of month : %x\n", &month);
printf("addr of array : %x\n", Table); // 배열명은 기본적으로 주소를 나타냄.
printf("addr of first element of array : %x\n", &Table[0]);
printf("addr of second element of array : %x\n", &Table[1]);
}
포인터변수의 선언
-
형식 : 자료형 *포인터변수명;
-
사용 예 : int *p;
-
기능 : 변수 p는 포인터 변수로서 정수형의 자료를 갖는 변수의 주소를 갖는다.
-
int *p
- p : 포인터 변수로서 정수 형 자료가 수록되어있는 주소를 갖고 있다.
- *p : 해당 주소에 수록되어 있는 정수 형 자료를 갖고 있다.
#include <stdio.h>
void main()
{
int a, b;
int *p; // 변수 p를 포인터 변수로 선언.
a = 5000;
p = &a; // 포인터 변수 p에 변수 a의 주소값 대입.
b = *p; // 포인터 변수 p가 가리키는 주소의 내용을, 변수 b에 저장.
printf("a : %d, b : %d, p : %x", a, b, p);
}
포인터변수의 참조
포인터 변수의 참조 => &, * 연산자 사용.
-
잘 못 된 예
-
포인터변수의 올바른 참조 방법.
-
포인터 변수의 참조 예
-
#include <stdio.h> void main() { int *p, i = 3, j; p = &i; // 포인터 변수 p가 변수 i의 주소를 가리킴. 주소값 확보. j = *p; // 포인터 변수 p가 가리키는 번지의 내용을 변수 j에 대입. j++; // 변수 j의 값을 1증가. printf("*p = %d\n", *p); printf(" p = %x\n", p); printf(" j = %d\n", j); } /** * p = &i; * 포인터 변수 p가 어느 공간을 가르킬 것인가. * 포인터 변수는 특정 기억공간을 가리키는 지시자이고, * 이 지시자가 어느 위치를 가르킬 것인지를 지정하는 것이 포인터 변수에서 제일 중요. */
-
-
포인터 변수 참조의 기억공간 표현
void 형 포인터
- 형식 : void *포인터명;
- 의미 : 프로그램 실행시에 자료형이 결정되는 경우에 사용.
- 저장하기 전에 명시적 형변환 필요.
void 형 포인터의 사용 예
#include <stdio.h>
void main()
{
int a = 100;
char b = 'B';
void *p = NULL; // void형 포인터를 선언 후 초기화
p = (int *)&a;
// void형 포인터 p에 int형 변수 a의 주소를
// 명시적 형변환을 이용하여 대입.
printf("*p = %d\n", *(int *)p);
p = (char *)&b;
// void형 포인터 p에 char형 변수 b의 주소를
// 명시적 형변환을 이용하여 대입.
printf("*p = %c\n", *(char *)p);
}
일반 변수와 표인터 변수의 비교
일반 변수 | 포인터 변수 | ||||
선언 | int a; | 정수형 변수 a 선언 | int *a; | 포인터변수 a를 정수형으로 선언 | |
값 할당 | a = 100; | 변수 a에 100 할당 | *a = 100; | a 주소에 100 할당 | |
주소 참조 | &a | 변수 a의 주소 | a | a 자체가 주소 | |
주소 연산 | 연산 불가능 | a--; | 포인터를 1 감소 |
포인터 연산
포인터가 선언 되어있을 때 포인터와 포인터와 끼리의 계산이 가능하다.
포인터와 기억공간의 대응 관계
포인터 변수에 +, -, ++, -- 연산자를 사용하는 연산
int a[10], *p, *q;
포인터 연산의 예
#include <stdio.h>
void main()
{
int *p, a[] = {10, 20, 30, 40, 50};
// 배열 첫 번째 요소의 주소값을 포인터변수 p에 저장.
p = &a[0];
printf("*p == %d\n", *p); // 10
// 포인터 p의 값 출력 후 주소를 1(4byte) 증가.
printf("*p++ == %d\n", *p++); // 10
// 포인터 p의 주소를 1(4byte) 증가 후 출력.
printf("*++p == %d\n", *++p); // 30
// 포인터 p의 주소를 2(8byte) 증가
p = p + 2;
printf("*p == %d\n", *p); // 50
printf("a[2] == %d\n", a[2]); // 30
// 포인터 p의 값에 2를 증가.
printf("*p + 2 == %d\n", *p + 2); // 32
}
#include <stdio.h>
void main()
{
int *p, *q;
int a[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
p = &a[3];
printf("*p == %d\n", *p); // 40
// *(p + 3)과 *p + 3은 다르다.
printf("*(p + 3) == %d\n", *(p + 3)); // 70
q = p + 3;
printf("*q == %d\n", *q); // 70
// 동일 배열을 가르키는 경우 두 포인터 간의 뺄샘.
printf(" q - p == %ld\n", q - p); // 3
printf(" p - q == %ld\n", p - q); // -3
// 두 포인터 간의 덧셈은 불가능.
//printf(" p + q == %d\n", p + q);
}
'Language > C' 카테고리의 다른 글
[C] 구조체와 공용체 -1 (0) | 2020.12.27 |
---|---|
[C] 배열과 포인터 - 3 (0) | 2020.12.27 |
[C] 배열과 포인터 - 1 (0) | 2020.12.25 |
[C] 함수와 기억 클래스 - 2 (0) | 2020.12.25 |
[C] 함수와 기억 클래스 - 1 (0) | 2020.12.20 |