공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
함수 포인터
프로그래머가 정의하는 모든 함수는 프로그램 실행 시 메인 메모리에 저장되어 실행된다. 배열처럼 함수의 이름은 함수가 저장된 메모리 공간의 주소 값을 의미하는데, 배열 이름과 마찬가지로 함수의 이름도 상수의 형태이다. 함수의 주소 값 저장을 위한 포인터 변수를 별도로 설정할 수 있는데, 이러한 포인터 변수를 '함수 포인터 변수'라고 한다.
함수 포인터 변수 선언
[반환형] (* [포인터 이름]) ([매개변수1 타입], [매개변수2 타입] ...)
// ex)
int SimpleFunc1(int num) {...}
void SimpleFunc2(char * str) {...}
// 함수 포인터 변수 선언
int (*fptr1) (int)
fptr1 = SimpleFunc1; // 대입 연산이 끝나면 함수 이름과, 함수 포인터 변수에는 동일한 값이 저장됨.
fptr1(3) // 대입 이후에는 포인터 이름으로 함수호출 가능
void (*fptr2) (char *) = SimpleFunc2; // 선언하면서 동시에 대입가능
함수 포인터 형(type)은 반환형과 매개변수의 선언을 통해서 결정짓는다. 그래서 반환형과 매개변수의 선언이 일치하면(매개변수의 type과 개수, 순서가 같으면) 함수 포인터 형도 일치한다. 함수 포인터 변수에 함수의 주소를 대입하고 난 이후에는 (동일한 값이 저장되어) 상수냐 변수냐가 이 둘의 유일한 차이점이 된다. 또한 함수 포인터 변수를 이용해서 함수를 호출하는 것도 가능하다.
#include <stdio.h>
void SimpleAdder(int n1, int n2)
{
printf("%d + %d = %d \n", n1, n2, n1+ n2);
}
void ShowString(char * str)
{
printf("%s \n", str);
}
int main(void)
{
char * str = "Function Pointer";
int num1 = 10, num2 = 20;
void (*fptr1)(int, int) = SimpleAdder;
void (*fptr2)(char *) = ShowString;
// 함수 포인터 변수에 의한 호출
fptr1(num1, num2);
fptr2(str);
return 0;
}
함수 포인터 변수를 선언하고 사용하는 예시이다.
#include <stdio.h>
int WhoIsFirst(int age1, int age2, int (*cmp)(int n1, int n2)) // 매개 변수의 선언으로 함수 포인터 변수가 올 수 있다.
{
return cmp(age1, age2); // (함수 포인터 변수인) 세번째 인자에 따라 다른 함수가 호출되어 리턴됨
}
int OlderFirst(int age1, int age2)
{
if(age1 > age2)
return age1;
else if(age1 < age2)
return age2;
else
return 0;
}
int YoungerFirst(int age1, int age2)
{
if(age1 < age2)
return age1;
else if(age1 > age2)
return age2;
else
return 0;
}
int main(void)
{
int age1 = 20;
int age2 = 30;
int first;
printf("입장 순서 1\n");
first = WhoIsFirst(age1, age2, OlderFirst);
printf("%d세와 %d세중 %d세가 먼저 입장 ! \n\n", age1, age2, first);
printf("입장 순서 2\n");
first = WhoIsFirst(age1, age2, YoungerFirst);
printf("%d세와 %d세중 %d세가 먼저 입장 ! \n\n", age1, age2, first);
return 0;
}
함수 포인터 변수가 매개변수로 오는 것도 가능하다.
위의 예시는 함수 포인터를 매개변수로 사용하고, 세 번째 인자에 따라 다른 함수가 동작한다.
void 포인터
void * ptr;
형(type)이 존재하지 않는 포인터를 ``void``포인터라고 한다. 어떠한 변수의 주소 값이든 다 담을 수 있고(원래 자료형이 다른 포인터끼리 메모리 주소를 저장하면 컴파일 경고(warning)가 발생한다.), 함수의 주소 값을 담는 것도 가능하지만, type이 없기 때문에 포인터 연산이 불가능하고 값의 변경이나 참조도 할 수 없다. 일단 주소 값에 의미를 두고 포인터 형(type)은 나중에 정해야 할 때 사용한다. 암시적으로 자료형이 변환되는 방식으로, 이러한 특성 때문에 void 포인터는 범용 포인터라고도 한다. void 포인터는 자료형이 정해져 있지 않아서 역참조를 할 수 없다. 메모리의 동적 할당에서 많이 사용한다.
#include <stdio.h>
void SoSimpleFunc(void)
{
printf("I'm so simple");
}
int main(void)
{
int num = 20;
void * ptr;
ptr = #
/* 아래 두줄은 컴파일 에러
*ptr = 20;
ptr++;
*/
printf("%p \n", ptr);
ptr = SoSimpleFunc;
printf("%p \n", ptr);
return 0;
}
void 포인터를 사용하는 예시이다. 포인터 연산이 불가능하기 때문에 주석 처리된 부분은 오류가 난다.
'기타 > C' 카테고리의 다른 글
[C] 문자, 문자열 (0) | 2020.05.28 |
---|---|
[C] 스트림, 버퍼 (0) | 2020.05.27 |
[C] 다차원 배열과 포인터 (0) | 2020.05.19 |
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |