다음 설명은 제 개인의 생각을 정리하는 글입니다. 부족한 부분도 많고 틀린 부분도 많으므로 읽으실 때 이점을 고려하셨으면 좋겠습니다.
또한 틀린 부분, 보완할 부분을 댓글로 달아주시면 더욱 감사하겠습니다 ^^
다만, 틀린 내용에 대해서 시비를 거는 행위는 좀 삼가셨으면 합니다^^
다음 예제는 특정 함수에서 주소를 반환하여 특정 함수에서 포인터에 주소를 저장하는 방법이다.
예제 앞서 혹여 다시 한번 포인터의 정의를 짚고 넘어가자.
포인터 : 메모리 주소를 저장하는 변수. 즉, 포인터는 주소를 저장하는 변수를 말한다.
단순히 변수명 뿐만 아니라 상수명, 구조체등 어떤 형식이든 관계없이 해당값에
접근할 수 있는 주소를 저장한다.
int *ptr; // *을 선언하는 순간 포인터임을 알려준다.
이때 * (애더리스크)의 의미는 "ptr에 저장되어 있는 주소를 찾아가서 읽고/쓰는 작업을 함"을 의미한다.
int num = 5;
ptr = # //여기서 *를 붙이지 않는 이유는 *의 의미가 '저장된 주소를 찾아가서 읽고/쓰는 작업/동작 함'을 의미하기때문에
주소를 저장해야 하는 시점에서는 연산자 * 가 동작하지 않아야 하기 때문이다.
*ptr = 7; // 이제 7을 저장하기 위해서 *를 붙였다. 왜? 연산자 * 가 자신의 기능을 수행해야 7이라는 값을 num에 쓸수있기때문이다.
현재 ptr에는 num의 주소값이 저장되어 있으므로 ptr앞에 * 를 붙이면 * 가 ptr에 저장되어 있는 주소값을 찾아가서
7이라는 값을 쓰는 기능을 수행한다.
-----------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int *sum(int a, int b); /* 함수명앞에 *를 붙이는 이유는 반환값이 값이 아니라 주소이기 때문에 주소를 저장하는 포인터를 사용해야해서
함수명앞에 *를 붙이는 것이다. */
int main()
{
int a, b;
int *tot;
a = 10;
b = 20;
tot = sum(a, b); /* tot와 sum이 모두 포인터 이기 때문에 굳이 *를 붙일 필요가 없다.*/
printf("%d\n", *tot); /*tot라는 변수는 선언된적이 없고 tot라는 포인터가 선언 되었다. 따라서 tot값을 표현하려면
포인터 tot를 가르켜야 하기 때문에 *를 붙여야 하는 것이다.*/
system("pause");
return 0;
}
int *sum(int a, int b) {
static int res; /* res변수의 메모리가 유지되어야 다른함수에서 불러 쓸수 있기 때문에 정적변수를 사용해야한다. */
res = a + b;
return &res;
}
----------------------------------------------------------------------------------------------------------------------------
위 함수를 보면 sum이라는 함수에서 res의 주소를 반환하여 main함수에서 tot가 res의 주소를 받아서 출력하는 단순한 예제이다.
위 예제에서 함수앞에 *를 쓰는 이유를 다시한번 설명하면 일반적으로 포인터를 선언할때 *를 붙인다. 함수역시 마찬가지로 sum함수를 선언하는데 이 함수가 주소를 반환하기 때문에 함수자체가 포인터 함수라고 생각하면 될듯하다. 즉 포인터함수이기 때문에 함수앞에 포인터 함수라는 표현을 하기 위해서 *를 붙이는 것이다. (실제 포인터 함수?? 는 아닐것이다. 아마 내 생각인듯....)
다음은 위 방법을 이용해서 로또 번호 추첨 코드를 작성하였다.
아래 코드는 로또 번호를 입력하면 랜덤번호가 생성되고 입력번호와 랜덤번호를 비교해서 당첨번호만 출력해주는 소스이다.
---------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int *input_data (void);
int *random_data (void); /* 둘다 주소를 반환할것이기 때문에 포인터함수를 선언하였다. */
void compare_data (void);
int main()
{
int sel;
printf("로또 뽑기(1) 종료(2)\n선택 :");
scanf("%d", &sel);
while (sel == 1) { /* while문을 작성한 이유는 껏다 키는것이 귀찮아서..이다. */
compare_data();
printf("\n\n로또 뽑기(1) 종료(2)\n선택 :");
scanf("%d", &sel);
}
return 0;
}
int *input_data (void) {
static int num[6];
int i;
printf("\n선택 번호 : ");
for(i=0;i<6;i++) {
scanf("%d", &num[i]);
}
return #
}
int *random_data (void) {
int i, j, r;
static int random[7];
srand(time(NULL));
for(i=0;i<=6;i++){
again:;
r=(rand()%49)+1;
for(j=0;j<=i-1;j++)
if(r==random[j])
goto again;
random[i]=r;
}
printf("추첨 번호 :");
for (i=0; i<7; i++){
printf("%3d", random[i]);
}
return &random;
}
void compare_data (void) {
int i, j;
int same = 0;
int *num_com, *random_com;
int select[6] = {0, 0, 0, 0, 0, 0};
num_com = input_data();
random_com = random_data();
printf("\n당첨 번호 :");
for(i=0;i<7;i++) {
for(j=0;j<6;j++){
if((random_com[i]) == (num_com[j])) {
select[j] = num_com[j];
}
}
}
for (i=0;i<6;i++){
if (select[i] != 0) {
printf("%3d", select[i]); same++;
}
}
printf("\n같은 번호 개수 :%d", same);
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------
input_data는 번호를 입력하여 저장하는 함수이다.
random_data 함수는 임의의 변수 7개를 생성하는 함수이다.
compare_data 함수는 input_data와 random_data함수의 번호를 비교하는 함수이다.
주소를 반환해서 포인터로 이용하는 방법을 선택한 이유는 한번 선언된 메모리의 주소값은 변하지 않는다.(내가 배운 시점까지는...)
따라서 해당값이 저장되어 있는 메모리의 첫번째 주소값만 알 수 있다면 그 주소값을 이용해 나머지 값도 이용할 수 있기때문이다.
(즉, 100번지에 첫번때 값이 저장되어 있다면 int형의 경우 104번지는 2번째 값 108번지는 3번쨰값......이 저장되어 있을것이기 때문이다.)
'프로그래밍 공부(정리) > C, C++' 카테고리의 다른 글
visual studio - "kernel32.lib"파일을 열 수 없습니다. 해결방법~ (4) | 2017.04.12 |
---|
댓글