9강 배열과 포인터 2
1.포인터의 개념
포인터는 변수의 일종
- 특정 데이터 값을 가지고 있음
- 특정 데이터가 저장된 기억장소의 주소(번지)값을 가지고 있음
- 포인터는 기억공간을 변수명으로 접근하지 않고 주소로 접근하기 위해 사용
일반적인 변수의 기억공간 표현
-변수는 변수 선언에 의해 기억공간이 할당되고
-할당된 기억공간에 변수에 대입된 데이터가 저장
-이떄 할당된 기억공간은 주소(번지)가 부여되어 있다.
int x
x= 200;
print("x=%d\n",x);
...
x라는 이름으로 200이 저장되었지만 별도의 주소가 있음
주소를 이용하여 변수와 같은 동일한 작업 가능
- 특정 주소(번지)를 이용하여 추가적인 데이터를 저장
- 즉 주소를 다루는 변수가 필요하다
- 포인트 변수 - 주소 값을 갖는 특별한 변수
// 변수의 주소 예
#include <stdio.h>
void main() {
int days = 365;
int month = 12;
int Table[5] = { 1, 2, 3, 4, 5 };
//앰퍼센트로 주소 확인
printf("days의 주소는 %x\n", &days);
printf("month의 주소는 %x\n", &month);
printf("배열명 Table 첫번째 요소의 주소는 %x\n", &Table[0]);
printf("배열명 Table 두번째 요소의 주소는 %x\n", &Table[1]);
}
/*주소값은 매번 변경됨
days의 주소는 b292fc74
month의 주소는 b292fc94
배열명 Table 첫번째 요소의 주소는 b292fcb8
배열명 Table 두번째 요소의 주소는 b292fcbc
*/
2. 포인터변수의 선언과 참조
포인트변수의 선언
*포인터변수명;
int *p;
변수p는 포인트 변수로서 정수형의 자료를 갖는 변수의 주소를 갖는다.
- 해당 주소에 수록되어 있는 정수형 자료를 갖고 있다.
포인터 변수의 사용 예
int a, b;
int *p; // p는 포인터 변수의 선언
a = 50000;
// 주소를 치환하여야 함(포인터 변수가 지정할 주소는 어디인가?)
p = &a; // p라는 공간에 a의 주소가 대입
b = *p;
포인터변수의 참소 => &, * 연산자 사용
1)
int *p, i=4;
*p=i;
-포인터변수 p가 기억공간 내 몇 번지를 가르키는지 알 수 없다.
2)
int *p, i=4
*p = 5;
- 무의미한 참조
올바른 참조
int *p, i = 4;
a = &i;
*p = 10;
// 포인트변수의 참조 예
#include <stdio.h>
void main() {
int* p, i = 3, j;
p = &i;
j = *p;
j++;
printf("*p = %d\n", *p);
printf("p = %x\n", p);
printf("j = %d\n", j);
}
/*
*p = 3
p = 651df9f4
j = 4
*/
포인터변수 참조의 기억공간 표현
int *p, i=3, j;
(3) void형 포인터
-프로그램 실행시에 자료형이 결정되는 경우
-저장하기 전에 명시적 형변환이 필요
//void형 포인터의 예
#include<stdio.h>
void main() {
int a = 100;
char b = 'b';
void* p = NULL; // 나중에 선언시 void, 주소를 명시적 형변환을 이용
p = (int*)&a;
printf("*p = %d\n", *(int*)p);
p = (char*)&b;
printf("*p = %c\n", *(char*)p);
}
/*
*p = 100
*p = b
*/
일반 변수와 포인트 변수 비교
포인트 변수 *
*a = 100 : a주소에 100을 할당 a자체가 주소, a-- 포인터를 1 감소
&a 주소참조
3.포인터연산
포인터와 기억공간의 대응관계
<int *p;의 경우 p=100일떄>
-두 번째 공간 p + 1, p + 2, p +3
-포인터를 1 증가시키면 실제 주소는 int형의 경우 4byte 증가
<char *p;의 경우 p=100 일때>
-포인터를 1증가시키면 실제 주소는 char형으로 1byte증가
포인터변수에 +, -, ++, -- 연산자를 사용하는 연산
int a[10], *p, *q
p = &a[2]
q = p + 3
p = p + 6
int a[10], *p, *q;
p=&a[7]
q=p-3
p=p-5
위치변환의 예
int a[10],. *p, *q;
p = &a[6]
q = &a[2]
i = p - q i=4
i = q - p i=4
-두 포인트간의 덧셈은 안됨
//포인터 연산의 예1
#include <stdio.h>
void main() {
int* p, a[] = { 10, 20, 30, 40, 50 };
// 배열의 첫 번째 요소의 주소값을 포인터변수 p에 저장
p = &a[0];
printf("*p == %d\n", *p);
//포인터 p의 값을 출력 후 주소를 1(4byte)증가
printf("*p++ == %d\n", *p++);
//포인터 p의 주소를 1(4byte)증가 후 출력
printf("*++p == %d\n", *++p);
//포인터 p의 주소를 2(8byte) 증가
p = p + 2;
printf("*p == %d\n", *p);
printf("a[2] == %d\n", a[2]);
//포인터 p의 값에 2를 더함
printf("*p+2 == %d\n", *p + 2);
}
/*
*p == 10
*p++ == 10 // p주소값 출력 후 값 증가 무의미
*++p == 30
*p == 50
a[2] == 30
*p+2 == 52 // 포인터 p의 값에 2를 더함(괄호 중요)
*/
//포인터 연산의 예 2
#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);
//*(p+3)과 *p+3에 주의
printf("*(P+3) == %d\n", *(p + 3));
q = p + 3;
printf("*q == %d\n", *q);
//두 포인터간의 뺼셈(동일 배열을 가르키는 경우)
printf("p - q == %d\n", p - q);
printf("q - p == %d\n", q - p);
//두 포인터간의 덧셈 불가능
//printf("q + p == %d\n, q + p )
}
/*
*p == 40
*(P+3) == 70
*q == 70
p - q == -3
q - p == 3
*/