공부했던 자료 정리하는 용도입니다.

재배포, 수정하지 마세요.

 

 


 포인터 

  1. 포인터
    • 포인터 변수
    • 포인터 변수의 선언
      * 포인터 변수의 크기
    • 포인터 형(type)
    • 포인터 변수와 관련된 연산자
      1. & 연산자
      2. * 연산자
    • null 포인터
    • 포인터 대상의 const 선언
      * 상수를 가리키는 포인터인 경우
      * 포인터 자체가 상수인 경우
      * 포인터가 상수이면서 상수를 가리키는 경우
  2. 포인터와 배열
    • 포인터 연산
    • 문자열의 선언방식
    • 포인터 배열
      * 문자열 배열
  3. 포인터와 함수
    • 함수의 호출 방식
      * Call-by-value
      * Call-by-reference
    • 함수의 인자로 배열 전달
      * 인자로 배열 전달 시 배열의 크기
  4. 이중 포인터(더블 포인터)
    • 이중 포인터 선언과 사용
    • 포인터 변수 대상의 Call-by-reference
    • 포인터 배열과 포인터 배열의 포인터 type
    • 다중 포인터 변수
  5. 다차원 배열과 포인터
    • 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
    • 2차원 배열의 증감 연산
    • 2차원 배열의 포인터
    • 함수 인자로 2차원 배열 전달
    • 다차원 배열에서 arr[i]와 *(arr + i)
    • 배열 포인터와 포인터 배열
    • main 함수의 인자
      * 인자의 형성 과정
      * char * argv[ ]
  6. 함수 포인터
    • 함수 포인터 변수 선언
  7. 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 = &num;
	/* 아래 두줄은 컴파일 에러
	*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

+ Recent posts