C언어에서 말하는 함수
사용자 정의 함수와 선언 및 정의
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include<stdio.h> int MyFunc(int nA, int nB) { printf("nA : %d \n", nA); printf("nB : %d \n", nB); return nA + nB; } int main(void) { int numA = 10; int numB = 20; int nSum = 0; nSum = MyFunc(numA, numB); return 0; } | cs |
# 프로그램을 실행하면 제일먼저 main() 함수로 진입을 합니다.
main() 함수는 항상 우선순위 1순위...
# 3번 ~ 9번 행 은 사용자 정의함수, MyFunc()의 선언 및 정의가 됩니다.
선언 : MyFunc() 함수에 대하여 골격을 뜻합니다. ( 건축에서 뼈대만 세운 것이죠 )
정의 : MyFunc() 함수 안에 있는 구문들을 뜻합니다.
# 잠시 여기서 호출자와 피호출자를 잠시 보고 갑시다.
호출자 : 자신 함수 구문 내에서 다른 함수를 호출 하였다면 ( 17번 행과같이 ) 호출자( Caller)라고 부릅니다.
피호출자 : 호출자(Caller)가 호출한 대상을 뜻합니다. 호출 당한놈! 피호출자( Callee )
본문으로 다시 넘어가면
# 3번 행을 살펴보면 아래와 같습니다.
int MyFunc(int nA, int nB) == 반환형식 함수명(매개변수1,매개변수2,...)
반환형식 : 함수 구문에서 return문을 만나서 호출자에게 어떤 값을 돌려줄지 자료형식을 작성합니다.
함수명 : 사용자가 정의하고자 하는 이름을 작성해줍니다.
매개변수 : 호출자가 전달하는 메모리의 값을 어떤 형식으로 받을 것인지 작성합니다.
# 디버그 모드를 통하여 한번 살펴보죠!!
그림에서 보면 17번 행에서 매개변수로 (numA,numB)를 피호출자에게 전달합니다.
피 호출자는 받은 값을 자신의 매개변수에 Copy&Overwrite하게 됩니다.
# 여기서 하나 알고 가야 할 것이 있습니다.
피호출자의 매개변수는 메모리에 저장될 때, 순서가 뒤에서부터 들어가게 된다는 것입니다.
nB가 메모리에 먼저 들어가게 되고 그 다음
nA가 메모리에 들어 간다는 것입니다.
자 디버그 모드로 한번 들어가 보겠습니다.
메모리를 보시게 되면 nB가 메모리에 먼저 적제 되었다는 것이 확인이 됩니다.
확인이 되었으면 계속 진행해보죠
3번 행에서 매개변수를 받고 5번6번 행에서 각 변수의 값을 출력합니다.
8번행에서 return nA+nB; 구문이 나타납니다.
이 부분이 앞서 말씀 드렸던 반환에 대한 문법입니다.
# return문을 작성하는 법은 아래와 같습니다.
return 변수값 ;
return 연산식;
return 문자열 혹은 상수값들;
return 함수();
경우에 따라서 사용하는 방법이 다를 수 있습니다.
만약 반환 형식이 void 라면 return문을 작성하지 않으셔도 됩니다~!!
8번 행에서 return문은 반환형식이 int 이므로 "return nA+nB;"를 하게 되면 호출자에게 "nA+nB" 의 합을 int형식으로 돌려줍니다.
# 아래의 그림에서 메모리를 살펴보시죠
"MyFunc이(가) 반환되었습니다" 라고 되어있고 값은 "30"이 들어있죠??
17번 행에서 한번더 F10을 눌러주게되면 반환된 값은 nSum 변수에 담기게 됩니다.
메모리를 보시면 16진수"0x1e" == 10진수"30" 이므로 리턴된 값 "30"이 들어있음을 확인 할 수 있습니다.
함수 설계할때 지켜주십쇼 하는것!! something??
함수 설계할때 지켜주십쇼 하는것!! #1 UI와 기능분리
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include<stdio.h> int divFunc(int nData){ int nCnt = 0; //약수 갯수 if (nData > 10 || nData < 0) //오류체크 { printf("ERROR!! 0~10 사이의 숫자를 입력하세요\n"); return 0; } for (int i = 1; i <= nData; i++) { if (nData % i == 0) ++nCnt; // 약수일때 nCnt값 증가 } return nCnt; //약수의 개수 리턴 } int main(void) { int nInput = 0; printf("약수 개수를 구할 1~10의 숫자 입력:"); scanf("%d", &nInput); printf("%d의 약수 개수:%d\n",nInput,divFunc(nInput)); return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include<stdio.h> int divFunc(int nData){ int nCnt = 0; //약수 갯수 if (nData > 10 || nData < 0) return 0; //오류체크 for (int i = 1; i <= nData; i++) { if (nData % i == 0) ++nCnt; //약수라면 nCnt 개수증가 } return nCnt; //약수의 개수 리턴 } int main(void) { int nInput = 0; printf("약수의 개수를 구할 1~10의 숫자 입력:"); scanf("%d", &nInput); int nResult = divFunc(nInput); if (nResult == 0) { puts("ERROR 1 ~ 10 의 숫자만 입력해주세요"); return 0; } printf("%d의 약수 개수:%d\n",nInput,nResult); return 0; } | cs |
어떤가요 ?? 앞서 본 코드와 달리 기능과 UI가 명확이 분리되었죠??
이런 방법으로 코드를 작성하는것이 중요합니다.
예재하나만 더 들어보겠습니다.
# 학점 계산하는코드입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //학점 입력하는 인터페이스 int GetResult(void) { int nInput = 0; printf("학점을 입력하세요:"); scanf("%d", &nInput); return nInput; } //학점 계산하는 인터페이스 char GetGrade(int nScore) { if (nScore > 90) return 'A'; else if (nScore > 80) return 'B'; else if (nScore > 70) return 'C'; else if (nScore > 60) return 'D'; return 'F'; } int main(void){ int nResult = 0; nResult = GetResult(); printf("%d점은 학점 %c 입니다.\n", nResult, GetGrade(nResult)); return 0; } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //학점 입력하는 인터페이스 int GetResult(void) { int nInput = 0; printf("학점을 입력하세요:"); scanf("%d", &nInput); if (nInput > 100 || nInput < 0) return 0; return nInput; } //학점 계산하는 인터페이스 char GetGrade(int nScore) { if (nScore > 90) return 'A'; else if (nScore > 80) return 'B'; else if (nScore > 70) return 'C'; else if (nScore > 60) return 'D'; return 'F'; } int main(void){ int nResult = 0; nResult = GetResult(); if (nResult == 0) { puts("ERROR!!! 1~100의 숫자만 입력하세요"); return 0; } printf("%d점은 학점 %c 입니다.\n", nResult, GetGrade(nResult)); return 0; } | cs |
함수 설계할때 지켜주십쇼 하는것!! #2 재사용 가능한 단위기능 구현
전역변수!!! 사용하기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #include<stdio.h> int g_money = 0; //입금 void KeepMoney(int nPrice){ g_money += nPrice; } //출금 void OutMoney(int nPrice){ g_money -= nPrice; } //메뉴선택 int GetMenu(){ int nInput = 0; int nMoney = 0; printf("[1]입금 [2]출금 \n>>"); scanf("%d", &nInput); if (nInput > 2 || nInput < 0) return 0; return nInput; } //금액선택 자주사용하게될 구문은 함수화!! int GetMoney(){ int IN_Money = 0; printf("금액을 입력해주세요 :"); scanf("%d", &IN_Money); return IN_Money; } int main(void) { g_money = 2000; //기본 돈 지정 int Menu = 0; while ((Menu=GetMenu()) != 0){ switch (Menu){ case 1: KeepMoney(GetMoney()); printf("현재 잔고: %d\n\n", g_money); break; case 2: OutMoney(GetMoney()); printf("현재 잔고: %d\n\n", g_money); break; default: printf("ERROR!!"); } } return 0; } | cs |
(이 예재는 조금 약할 수도 있습니다.)
2번 행을 보면 전역변수 g_money 를 선언 및 정의하였습니다.
코드를 보시면 함수 부분부분에서 전역변수 g_money 를 사용합니다.
# g_money를 자료형과 식별자명을 변경한다고 생각한다면..
수정해야할 것들이 많이 보이겠죠..??
그렇다면 어떻게 코드들을 작성해야할까요?
# 좋은설계는 간단합니다.
프로그램을 적절한 단위요소로 나누고
각 요소가 다른 요소의 변화에 영향을 받지 않도록
의존성을 최대한 낮추는 것입니다.
그렇게 해서 테스트도 좋고 유지보수 하기도 좋게 만들어 생산성을 향상시키면 됩니다.
'훈, IT 공부 > C,C++,MFC' 카테고리의 다른 글
포인터에 대해서 깊고 세밀하고 정확하게 이해하기!!! (0) | 2018.01.24 |
---|---|
[프로그램]숫자 야구 게임 (3) | 2018.01.24 |
헝가리안 표기법이란 (0) | 2018.01.04 |
ASLR이란? 왜 계속 주소가 바뀌는건가요!!! (메모리변조) (0) | 2018.01.03 |
[실습코딩] 정렬 코드화 하기 ( 버블, 선택, 선택으로 알려진 버블) (0) | 2018.01.01 |
댓글