배열을 포인터 형으로 바꾸기
int data[3];
data[2] = 2;
*(data + 3) = 2;
int data[2][3];
data[1][2] = 3;
data[1]을 A로 치환한다.
A[2] = 3;
*(A + 2) = 3;
*(data[1] + 2) = 3;
*(*(data + 1) + 2) = 3;
함수 포인터
함수의 포인터는 기계어 명령문을 가리킬 수 있는 포인터이다. 함수의 ip를 기억했다가 사용한다.
일반적인 포인터는 데이터 포인터를 말한다. 즉, 행위는 그대로이지만 매개변수의 조건을 바꾸어줄 수 있다.
특정 함수를 구성하는 시작 명령의 위치를 가리키는 포인터이다. 함수의 포인터를 이용하여 주로 함수를 호출하여 실행한다.
int Sum(int a, int b)
{
int res = 0; // 이 명령문이 저장된 위치의 주소가 Sum 함수의 시작 주소와 같다.
res = a + b;
return res;
}
int res = Sum(2, 3);
∑ // Sum 함수의 첫 번째 명령문의 주소를 의미한다. & 연산자가 생략 가능해 함수의 이름(Sum)만 적어도
해당 함수 첫 번째 명령문의 주소를 의미한다.
함수의 주소 값으로 함수 실행하기
함수 포인터는 함수 원형을 사용해서 포인터를 선언한다.
함수 포인터 선언 및 함수의 주소 대입
int (*p) (int, int) // Sum 함수를 가리킬 수 있는 포인터를 한다. 매개변수의 개수, 매개변수의 자료형을 알아야 한다.
이 포인터가 가리키는 함수를 호출 하는데 2, 3을 매개변수로 가진다.
p = &Sum // Sum 함수의 주소를 p에 저장한다.
함수 포인터로 함수 호출하기
int res = (*p)(2, 3) // int res = Sum(2, 3); 과 동일하다.
이렇게 복잡하게 함수의 포인터를 사용하는 이유는 구체적인 대상이 없어도 사용가능하기 때문이다.
일반적인 포인터와 마찬가지로 함수 포인터도 행위만 있지 대상은 정해지지 않았다. 나중에 호출할 때 대상만 정해주면 된다.
함수의 원형이 같은 함수들을 묶기
함수의 포인터로 같은 수의 매개변수와 자료형 그리고 같은 형태의 반환 값을 가지는 함수들을 그룹으로 묶을 수 있다.
위 사칙연산들은 함수의 원형이 같다. int [연산이름](int a, int b); 즉, int (*p) (int, int) 형으로 묶을 수 있다.
int (*p) (int, int)로 사칙연산의 함수를 모두 호출할 수 있다.
int (*p[4]) (int, int) = (&Sum, &Sub, &Mul, &Div); // &연산자 생략 가능하다. 함수의 포인터도 배열을 사용할 수 있다.
라이브러리를 만드는 라이브러리 프로그래머
라이브러리 프로그래머(판매자)는 자신의 기술로 함수를 만들어 함수를 라이브러리 형식의 파일로 사용자(구매자)에게 판매한다. 사용자는 라이브러리를 받아서 헤더 파일에 선언하면 함수를 사용할 수 있다.
라이브러리 프로그래머의 고민
고객의 요구가 늘어나면서 프로그래머가 계속해서 고객에 요구에 따라 소스코드를 수정하고 재배포하는 것은 매우 힘들다. 즉, 고객의 모든 요구를 반영할 수 없다. 이런 재배포가 힘든 상황에서 라이브러리에 포함된 함수는 본래의 기능을 유지하고 사용자가 원하는 경우에 사용자가 직접 함수의 기능을 수정해서 상용할 수 있도록 제공하는것이 함수 포인터의 기능이다.
void (*p) (int *); // 반환값이 없고 매개변수로 int * 형을 받을 수 있는 함수의 포인터이다.
매개 변수로 받은 두개의 수의 합을 구하는 함수를 만든다고 가정해보자. 아래와 같이 사용해 주면 된다.
int k = Sum(2, 3, NULL); // 원래 함수의 덧셈 기능만 사용할려면 NULL을 추가로 적어준다.
int Sum(int a, int b, void (*fp) (int *)) // void (*fp) (int *)는 함수의 포인터이다.
{
return a+b;
}
만일 사용자의 요구가 a에 음수가 오더라도 양수로 바꿔서 더하라는 요청이 온다면 아래와 같이 작성하면 된다.
int k = Sum(2, 3, Modify); // 변형해서 사용할 때 Modify가 먼저 호출된다.
int Sum(int a, int b, void (*fp) (int *)) // void (*fp) (int *)는 함수의 포인터이다.
{
if( fp != NULL) (*fp)(&a); // 이 함수는 a에 대해서 미래를 예측할 수 있다. 즉, 미래를 대처할 수 있는 함수이다.
return a+b;
}
void Modify(int *a) // 사용자의 요구가 직접 반영되는 부분이다.
{ // 사용자가 직접 작성한다.
if(*a<0)
*a = *a * -1;
}
위 함수를 보면 Sum 함수는 바뀌지 않고 사용자가 Modify를 추가한 것이다. Modify 함수로 인해 Sum 함수가 바뀌는 구조이다.
또한 Sum 함수를 만들 때 함수 포인터를 사용하면 사용자가 만든 Modify 함수가 없어도 에러 없이 컴파일이 된다.
콜백 함수
명시적으로 호출한것이 아니라 함수 포인터에 의해서 호출된다. 자싱이 함수를 구현했지만 언제 어떻게 호출되는지 알 수 없다.
c++
c, c++언어는 철학의 차이이다.
c, c++은 누가 더 좋다의 문제가 아니라 누가 더 어떠한 상황에 적합한것 인지의 차이이다.
c, c++은 성향 차이일 뿐 c, c++은 호환이 가능하다.
c언어는 절차 지향 프로그램이고 c++언어는 객체 지향 프로그램이다. 하지만 객체 지향 프로그램은 모두 c++을 가리키는것이 아니며 많은 객체 지향 프로그램 중 하나가 c+언어일 뿐이다. 또한 간혹 "c++이 객체 지향 프로그램이 아니다"라고 말하는 사람이 있는데 그 의미는 c++언어가 객체 지향만 할 수 있는 언어가 아니라 다양한 기능을 할 수 있다는 뜻이다.
c는 묘사하는 문법이다. 필요한 함수가 생기면 그때 그때 만들어서 사용한다.
c++은 절략을 짜는 문법이다. 전략을 우선 짜고 프로그래밍을 하는 언어이다. 전략을 잘 짜는 것은 경험에서 나온다. 또한 이론적으로 좋아지고 있는 문법들이 보강되고 있다.
c언어의 장점 : 효율이 좋다.
c언어의 단점 : 내부적 변화에 좋지 않다. 변화에 대처하기 힘들다. 함수와 데이터가 직접 대면하는 관계이기 때문에 데이터에 변화가 오면 함수에 영향을 미친다.
c++언어의 장점 : 변화에 영향을 받지 않는다. 융통성이 좋아진다.
c++언어의 단점 : 속도가 느리다.
c++은 객체 단위로 묶어서 자신이 해야할 일(역할)이 줄어든다.
c++은 사용자를 위한 문법(언어)이 아니라 프로그래머를 위한 문법(언어)이다.
프로그램은 데이터와 함수로 이루어져 있다. 데이터는 함수가 사용하는 것이다. 모든 함수는 데이터를 바라 보고 있는 구조이다.
즉, 변화는 데이터에 있다. 이 데이터가 모든 변화의 키이다. 이 데이터를 어떠한 관점에서 바라보는가가 데이터 유지보수의 키이다.
데이터의 변화를 줄이고 막아야 할 때 데이터가 바뀌는 길목을 최대한 하나로 줄이면 된다. 이렇게 되면 예외, 현상은 길목에서 잘 대처하면 된다.
c++ 문법이 데이터가 바뀌는 길목을 하나로 줄여준다. 따라서 데이터 변화 대처가 용이하다.
규칙을 찾고 표준을 찾아서 객체를 만드는 것이 c++ 언어의 특징이다.
객체(Object)란 무엇일까?
일상적인 행위나 작업을 표준화 시켜 하나의 제품으로 만들어 놓은것이다. 비슷한 행위가 반복되는것 중 표준적인 행위를 꾸며 제품으로 만드는 것이다.
함수 vs 객체
함수는 명령을 그룹짓는다.
객체는 함수를 어떻게 사용해야 하는지 그룹 짓는 행위이다.
객체와 c의 차이
프로그램을 하나 만들었다면 그 다음 만들 프로그램은 비슷한 프로그램을 만들 확률이 매우 높다.
새로운 프로그램을 잘 만드는것 보다 기존의 프로그램을 잘 활용하는것이 더 중요하다.
c++ 언어는 처음 만들 때는 힘들지만 한 번 만들면 생산성이 매우 좋다. 생산성이 매우 좋도록 입각해서 만들어진 언어이다.
'Programming > TIPS 17기' 카테고리의 다른 글
Day-13 C++ 이야기3 (0) | 2017.08.14 |
---|---|
Day-12 C++ 이야기2 (0) | 2017.08.11 |
Day-10 다차원 포인터, 구조체와 연결리스트 (0) | 2017.07.30 |
Day-9 메모리 할당, 다차원 포인터 (0) | 2017.07.28 |
Day-8 표준 입력 함수, 배열과 포인터 (2) | 2017.07.22 |