1. 포인터 변수로 배열의 주소를 받는 경우.
int arr[4] = {2, 4, 7, 9};
int * p;
p=arr;
arr[2] = 100; //이렇게 대입할 경우.
//다음도 가능하다.
p[2] = 100;
*(p+2) = 100;
2. 이중 포인터 : 포인터 변수의 주소를 저장하는 포인터 변수.
1) 포인터 변수를 교환하는 함수의 매개변수
#include <stdio.h>
void swap_ptr(char** ppa, char** ppb);
int main(void)
{
char* pa = "success";
char* pb = "failure";
printf("pa -> %s, pb -> %s\n", pa, pb); // 바꾸기 전에 문자열 출력
swap_ptr(&pa, &pb); // 함수 호출
printf("pa -> %s, pb -> %s\n", pa, pb); // 바꾼 후에 문자열 출력
return 0;
}
void swap_ptr(char** ppa, char** ppb) //바로 이곳!!! 함수의 매개변수!!!
{
char* pt;
pt = *ppa; // "success" 라는 문자열 주소 이동
*ppa = *ppb;
*ppb = pt;
}
2) 포인터 배열을 처리하는 함수의 매개변수
#include <stdio.h>
void print_str(char** pps, int cnt);
int main(void)
{
char* ptr_ary[] = {"eagle", "tiger", "lion", "squirrel"}; // 초기화
int count; // 배열 요소 수를 저장할 변수
count = sizeof(ptr_ary) / sizeof(ptr_ary[0]); // 배열 요소의 수 계산
print_str(ptr_ary, count); // 배열명과 배열 요소 수를 주고 호출
return 0;
}
void print_str(char** pps, int cnt) // 매개변수로 이중 포인터 사용
{
int i;
for (i = 0; i < cnt; i++) // 배열 요소 수만큼 반복
{
printf("%s\n", pps[i]); // *(pps+i)로도 쓸수 있다.
}
}
3. 포인터 배열 : 어렵게 생각하지 말고, 주소(=배열명)를 저장하는 배열이라 생각하면 된다.
#include <stdio.h>
int main(void)
{
int ary1[4] = { 1, 2, 3, 4 }; // 1차원 배열의 선언과 초기화
int ary2[4] = { 11, 12, 13, 14 };
int ary3[4] = { 21, 22, 23, 24 };
int* pary[3] = { ary1, ary2, ary3 }; // 포인터 배열에 각 배열명(=배열의 주소) 초기화
int i, j; // 반복 제어 변수
for (i = 0; i < 3; i++) // 3행 반복
{
for (j = 0; j < 4; j++) // 4열 반복
{
printf("%5d", pary[i][j]); //<- 배열표현 // 포인터 표현 : *(pary[i]+j)
}
printf("\n"); // 한 행을 출력한 후에 줄 바꿈
}
return 0;
}
4. 배열 포인터 -> 보통 2차원 배열 값을 받을 때 많이 씀. (1차원도 가능)
int (*p)[4] => int형 요소 4개를 저장하는 배열(ex: arr[4])의 주소(arr)를 저장하는 "포인터"
- 이차원 배열의 배열명을 받는 함수의 매개변수로 사용
#include <stdio.h>
void func(int(*)[4]);
int main(void)
{
int ary[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
func(ary); // 배열명을 인수로 주고 함수 호출
return 0;
}
void func(int(*pa)[4]) // 1행당 4개의 요소를 가지는 배열의 주소를 저장한다.
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%5d", pa[i][j]); // pa를 2차원 배열처럼 사용 //포인터식 *(pa[i]+j)로도 가능
}
printf("\n");
}
}
5. 고정되어 있는 주소 값을 포인터 상수(int * const p 처럼 주소 값이 고정되어 있는 거)라고 표현하기도 한다.
6. 함수 포인터 : 함수포인터도 결국 포인터이다. 어렵게 생각할 것 없이, 함수들의 주소(=함수명)를 저장하는 변수로 볼 수 있다.
1) 함수 자체를 매개변수로 받고 싶을 때. - 코드를 더 간결화 할 수 있다.
2) 다른 파일에 있는 정적함수 (static 함수)를 호출할 때 함수의 주소로 접근하여 호출 할 때.
3) call back 기능 구현 시 사용된다. 함수 포인터는 대상이 실재하지 않더라도 비워두고 프로그래밍을 진행할 수 있다.
=> 프로그램을 제작하는 그 당시에는 존재하지 않는 함수"를 호출할때 이용. ( 예를 들면 프로그램에 플로그인 기능이 필요한 경우, 플러그인은 아직 존재하지 않고 나중에 추가 될 수 있기 때문에 프로그램에서는 함수 포인터로 플러그인 함수에 접근한다.)
7. 함수 포인터 배열 예시. -> 함수 포인터 배열의 각 인덱스에 각 함수의 메모리 주소를 저장한다.
#include<stdio.h>
int add(int a, int b);
int sub(int a, int b);
int mul(int a, int b);
int main(void){
int (*fp[3])(int, int);
int sel, num1, num2;
printf("메뉴 입력 : 더하기 0번, 빼기 1번, 곱하기 2번\n");
scanf("%d", &sel);
printf("계산할 식 2개 입력\n");
scanf("%d %d", &num1, &num2);
fp[0]=add;
fp[1]=sub;
fp[2]=mul;
printf("이것이 결과 : %d\n", fp[sel](num1, num2));
return 0;
}
int add(int a, int b){
return a + b;
}
int sub(int a, int b){
return a - b;
}
int mul(int a, int b){
return a * b;
}
*) 함수 포인터에 배열을 사용하여 배열의 각각의 요소에 함수가 들어가 있는 것을 볼 수 있다.
*) 성격이 비슷한 함수를 묶어 사용할 때 유용할 것 같다. => 코드 간결화 가능
8. void 포인터 : 자료형이 정해지지 않은 포인터. 어떤 자료형이든 주소 저장이 가능하지만 사용(출력)시엔 형 변환 연산(캐스팅)을 통해 자료형을 맞춰주어야 한다. (ex : void *vp)
* 개인적인 학습 목적으로 작성한 글이기에 내용에 잘못된 정보가 있을 수 있습니다.
'임베디드 개발(before) > IoT 임베디드 SW 개발자 양성과정' 카테고리의 다른 글
[10일차] C언어 교육-(파일 개방과 입출력 함수) (0) | 2020.07.24 |
---|---|
[9일차] C언어 교육-(함수 포인터, 동적 할당 메모리, 구조체 등) (1) | 2020.07.23 |
내가 보려고 정리해둔 C언어 (0) | 2020.07.21 |
[7일차] C언어 교육7-(2차원 배열, 포인터 배열 등) (1) | 2020.07.21 |
[6일차] C언어 교육6-(새롭게 진도 나감. ~포인터, 배열) (1) | 2020.07.20 |