C언어 보충4 - 15장
15장. 응용포인터
1. 단일 포인터
- 포인터 변수의 값은 대상의 주소를 저장하고 포인터는 그대상을 가리킨다(의미한다)
- 정의방법
int a, b;
① int *pa=&a;
② int *pb;
pb=&b;
③ *pa=10;
- 포인터 사용방식
① (배열을 이용하지 않고)문자열을 사용할 때
- ex1)
char *pa="apple";
- ex2)
char *pa;
pa="apple";
② 배열자체를 가리킬때(배열처럼 사용이 가능하다)
- ex1)
int ary[3];
int *pa=ary;
- ex2)
int ary[3];
int *pa;
pa=ary;
③ 포인터 배열(=2차원 배열처럼 사용할 때) //배열의 요소가 모두 포인터인 배열
- ex)
int ary1[2];
int ary2[2];
int ary3[2];
int *pa[3]={ary1, ary2, ary3}; //요소가 포인터(int *)임으로 들어가는 값은 주소이다
pa[1][0]=10; //ary2[0]=10이다(=ary2배열의 첫번째 요소가 10이다)
*(pa[0]+1)=20; //ary1[1]=20이다
- 이해를 위한 비교
pa[0]은 ary1을 의미하고, pa[0][1]은 ary1[1]을 의미한다
더 정확히하면 pa[0]='ary1의 시작주소'이고 정수연산을 한다면 ary1[1]=*(ary1+1)=*(pa[0]+1)=pa[0][1]이다
④ (배열을 넘기기 위해)함수의 매개변수로서 사용
- ex)
int func(int *pa); //배열을 매개인자로 받기위해 포인터를 사용해 배열의 주소를 넘겨받음
void main()
{
int ary[5];
func(ary);
...
}
※ 포인터를 이용한 배열의 경우
- *(pa+0)=10; //배열의 첫번째요소를 10으로
- pa[1]=20; //배열의 두번째요소를 20으로
- scanf("%d", pa+2); //(배열 3번째 요소의 주소를 넣어) 배열의 3번째 인자값을
이 3가지 모두 적용할 수 있다
※ 만일 함수의 매개변수 자리에 (배열을 인자로 받기위해)배열을 선언하면 배열명은 포인터로 바뀐다.
ex) int func(int ary[5]) --> int func(int *pa)
=> 그대로 사용해도 문제는 없지만 이왕이면 포인터로 사용하자
※ 포인터 배열과 배열포인터간의 차이
- 포인터배열은 배열의 요소가 모두 포인터인 배열이다.
정의: int *pa[];
위의 정의는 int *(pa[])와 같다
배열 pa에 들어가는 요소는 모두 int *형이고, 이러한 변수에 들어가는 값에는 포인터가 가리키는 대상(int형)의 주소가 들어간다
만일 포인터가 가리키는 대상이 int형 일반변수라면(int a라 가정) int *pa[0]=&a; 이다
만일 포인터가 가리키는 대상이 int형 배열이라면(int ary[3]이라 가정) int *pa[0]=ary이다
- 배열포인터는 배열을 가리키는 포인터를 의미한다.
정의: int (*pb)[];
배열 포인터는 보통 2차원 배열을 가리키는 포인터로 사용한다
ex)
int ary[3][4];
int (*pa)[4];
pa=ary;
printf("%d", pa[1][2]);
- *pa는 이차원 배열인 ary[3]을 가리키며 *pa의 자료형은 int[4]형이다. 마찬가지로 pa는 int[4] *형이다
- 증명은 너무길어 하단의 상세증명으로 따로 적어두었다.
- 상세증명
int ary[3]; 이고 pa=ary일때
- 1차원 배열의 이름은 첫번째요소의 주소(=배열의 시작주소)를 의미한다
- 배열의 요소는 int형이다
- pa는 요소의 주소이다(실제로 주소연산시 pa+1을 하면 배열의 2번째 요소를 가리킨다)
- *pa가 배열의 요소를 의미하기때문에 *pa는 int형이고, pa는 int *형이다
int ary[3][4]; 이고 pa=ary일때
- 2차원 배열의 이름은 1차원배열의 시작주소(=2차원배열의 시작주소)를 의미한다
- 2차원배열의 요소는 int형이다
- 1차원배열의 요소는 int형 배열이다
- pa는 1차원배열의 시작주소(=1차원 배열의 첫번째 요소의 주소)이다
- *pa가 1차원 배열의 요소를 가리키기 때문에 *pa는 int형 배열형(정확히는 int[4]형)이고, pa는 int[4] *형이다
=>증명에 관한 더 자세한 내용은 책과(459.p, 461.p~)필기자료를 찾아보자(c프로그래밍 필기자료 1~2주)
2. 이중포인터
- 포인터를 가리키는 포인터
- 포인터 사용방식
① (포인터를 넘기기 위해) 함수의 매개변수로서 사용
- 보통 단일포인터를 넘기는 경우는 거의 없다(변수로 넘기지)
- 대표적인 경우는 포인터를 사용해 문자열을 표현하여 서로의 연결을 해제할 수 없고, 이를 다른 함수에서 교체하고할경우나,
- 하위블록에서 static변수를 사용하여(계속 살아있으니 접근가능, 하위 블록에서 return등으로 static변수의 주소를 넘긴다), 하위블록의 변수에 접근하고자 할 경우가 있다.(즉 매개변수로는 1가지..)
- ex) 사실 책 451.p 예제를 보는것이 더 빠르다..
char *b="abc";
swap(&b);
void swap(chat **c)
{
//포인터 주소 교체작업
}
② (포인터 배열을 넘기기 위해) 함수의 매개변수로서 사용
- 일반적인 일차원 배열을 넘길때는 단일포인터가 사용되나, 배열의 요소에 포인터가 있는 포인터배열은 이중포인터를 사용한다
- ex)
int *pa[3]; //포인터배열
func(pa);
void func(int **ppa)
{
...
}
③ (2차원 배열을 넘기기 위해) 함수의 매개변수로서 사용
- 일차원 배열을 넘길때는 단일포인터가 사용되니, 2차원 배열 넘길때는 이중포인터사용
- ex)
int ary[3][4]; //이차원 배열
func(ary);
void func(int **ppa) //*ppa는 ary[3]이고 **ppa는 ary[3][4]이다.
//좀더 자세히 보자면, ary[1][2]=*(ary[1]+2)=*(*(ary+1)+2)=*(*(ppa+1)+2) [매개변수를 ary=ppa로 설정하였으니]
// =*(ppa[1]+2)=ppa[1][2]
{
...
}
④ (이중포인터는 아니지만) 2차원 배열을 넘기기 위해 배열 포인터를 함수의 매개변수로서 사용
- 배열 포인터는 배열을 가리키는 포인터를 의미한다
- 이러한 배열포인터는 보통 2차원 배열을 가리키는 포인터로 사용한다(상단의 ※ 포인터 배열과 배열포인터간의 차이 참조)
- 일차원 배열을 함수로 넘기기위해 매개변수를 단일 포인터를 쓰듯, 2차원배열 또한 이중포인터 혹은 배열포인터를 이용한다
- ex)
int ary[3][4]; //이차원 배열
func(ary); //여기까지는 ③과 같다
void func(int (*pa)[4]) //배열포인터 사용 (함수의 매개변수 pa=ary)
{
...
}
3. 함수 포인터
- 임의의 함수를 지정하여 함수를 호출할 때(즉, 특정하게 함수를 지정하지 못할때). 혹은 함수정의 시점에서 함수를 결정하지 못하는 경우에 사용
- ex)
int sum(int a, int b);
{
return (a+b);
}
int (*fp)(int, int); //가리키는 대상이 함수임을 나타내기 위해 나타내기 위해 (*fp)를 해야한다.
fp=sum; // 배열명 처럼 함수명도 시작주소가 될 수 있다
result = fp(10,20);
4. void 포인터
- 가리키는 자료형이 정해지지 않은 포인터
- 보통 주소는 가리키는 대상의 자료형이 일치하는 포인터에만 대입이 가능하나, void포인터를 선언하는 것은 가리키는 자료형을 결정하지 않겠다는 의미이며, 따라서 모든주소를 저장 수 있다. 하지만 간접참조연산(ex: *vp)이나 정수연산(ex: vp+1)같은 주소연산이 불가능하다
- ex) 일반 포인터와 void포인터 간의 차이
int *ip <--> void *vp
ip=&a <--> vp=&a
*ip <--> *(int *)vp //대상에 접근하기위해(간접참조연산)서는 형변환이 필요
ip+1 <--> (int *)vp+1 //정수연산위해 형변환 필요
'Study > 프로그래밍_언어' 카테고리의 다른 글
C언어 보충6 - 18, 19장, 추가사항 (0) | 2018.02.03 |
---|---|
C언어 보충5 - 16, 17장 (0) | 2018.02.03 |
C언어 보충3 - 13, 14장 (0) | 2018.02.02 |
C언어 보충2 - 11, 12장 (0) | 2017.12.06 |
C언어 보충1 - 10장 (0) | 2017.12.02 |