< 함수 이해하기 >
> 함수 (Function) 의 개요
1) 함수란?
(1) 반복되어 실행될 명령문들을 모아 놓은 모듈
(2) 소스코드의 중복 회피
(3) 소스코드의 단순화
2) 함수의 종류
- 라이브러리(Library) 함수 : C언어 컴파일러에서 제공하는 함수
- 사용자 정의(User defined) 함수 : 프로그래머가 만들어서 사용하는 함수
3) main( ) 함수
- 프로그램이 시작되면 호출되는 첫 번째 함수
4) 라이브러리 함수
(1) include 문으로 라이브러리를 지정함
(2) 라이브러리에 정의된 함수를 호출하여 사용
#include <stdio.h> // Library
int main()
{
int a;
printf("Hello Wordld\n"); //input print
scanf_s("%d", &a); //output scanf
return 0;
}
5) 사용자 정의 함수
(1) 사용자 정의 함수의 구조
// 반환값이 있는 경우
int test(int a, int b)
{
int c = a * b;
return c;
}
// 반환값이 없는 경우
void test2(int x, int y)
{
int z = x + y;
return; // 생략가능
}
***
int : 함수의 반환값 자료형
test : 함수이름
(int a, int b) : 입력 매개 변수
int c = a * b : 함수 본체
return c : 반환문
(2) 반환값 자료형 규칙
- 반환값이 있는 경우 : return 문에서 반환하는 값의 자료형과 일치해야 함
- 반환값이 없는 경우 : void 로 정의하고, return 문을 생략할 수 있음
> 함수 사용하기
1) 사용자 정의 함수 호출
(1) 함수의 호출 과정
#include <stdio.h>
int main()
{
int result = 0;
result = test(10, 5);
printf("%d", result);
return 0;
}
int test(int a, int b)
{
int c = a * b;
return c;
}
(2) 인수와 매개변수
- 인수 : 함수를 호출할 때 전달하는 값
- 매개변수 : 함수를 호출할 때 전달되는 인수의 값을 저장하는 변수
- 인수와 매개변수는 나열한 순서대로 1:1 매칭
- 인수와 매개변수는 자료형이 일치하여야 함
2) 인수 전달 방법
(1) 인수 전달 방법의 종류
- 값에 의한 호출 (call by value)
: 인수의 값이 전달됨
#include <stdio.h>
int test(int a, int b)
{
a += 10;
b += 10;
return a + b;
}
int main()
{
int result = 0;
int x = 10, y = 5;
result = test(x, y);
printf("%d, %d", x, y); // 10, 5
return 0;
}
* 인수의 값만 매개변수에 전달됨
- 참조에 의한 호출 (call by reference)
: 인수의 포인터(메모리 주소값)가 전달됨
#include <stdio.h>
int test(int* a, int* b)
{
*a += 10;
*b += 10;
return *a + *b;
}
int main()
{
int result = 0;
int x = 10, y = 5;
result = test(&x, &y);
printf("%d, %d", x, y); // 20, 15
return 0;
}
* x 와 y의 주소값을 test 함수의 포인터 변수로 선언된 매개변수 a 와 b로 전달
3) 함수의 원형 (prototype)
- 함수의 원형이란
: 함수를 정의하기 전에 함수가 존재한다는 것을 선언하는 것
- 함수의 원형 선언 방법
: 함수의 머리 부분을 동일하게 선언하고, 세미콜론(;)을 마지막에 붙여줌
#include <stdio.h>
int test(int a, int b); // 함수의 머리부분에 ( ; ) 세미콜론 : 함수의 원형
/*
code
*/
int test(int a, int b) // 함수 머리부분
{
// 함수 본체부분
}
- 함수의 원형 선언 여부
** 함수의 원형을 선언해야 하는 경우 : 함수 호출 후에 함수를 정의하는 경우
#include <stdio.h>
void test(int a, int b); // 함수 원형 반드시 선언
int main()
{
int x, y;
test(x, y); // 함수 호출
}
void test(int a, int b) // 함수 정의
{
}
** 함수의 원형을 선언하지 않아도 되는 경우 : 함수 호출 전에 함수를 정의하는 경우
#include <stdio.h>
// void test(int a, int b); // 함수 원형 선언 안해도됨
void test(int a, int b) // 함수 정의
{
}
int main()
{
int x, y;
test(x, y); // 함수 호출
}
> 함수 기본 실습
#include <stdio.h>
// 함수 선언
int add(int a, int b) // Call by value (값에 의한 호출) 덧셈 함수
{
int ret = 0;
a += 10;
b += 10;
ret = a + b;
return ret;
// return a + b; // 직접 수식을 적어도 됨
}
void subtract(int a, int b) // 반환값이 없는 함수, 뺄셈 함수
{
printf("%2d - %2d = %d\n", (a * 2), (b * 2), (a * 2) - (b * 2));
}
int multiply(int* a, int* b) // Call by reference (참조에 의한 호출), 곱셈함수
{
int ret = 0;
*a += 10;
*b += 10;
ret = *a * *b;
return ret;
}
void printTitle()
{
printf("함수 기본 실습\n");
}
void printString(char* a)
{
printf("%s\n", a);
}
void operation(int a, char op, int b); // 함수 호출 main 함수 위에 위치
int main() // main 함수
{
int x = 10, y = 5, result = 0;
printTitle();
printString("덧셈계산");
result = add(x, y);
printf("x = %d, y = %d, result = %d\n", x, y, result);
printString("뺄셈계산");
subtract(x, y); // 위 덧셈과 달리 반환 result 변수가 없기 때문에 바로 출력
printString("곱셈계산");
result = multiply(&x, &y);
printf("x = %d, y = %d, result %d\n", x, y, result);
printString("사칙연산 함수 호출");
operation(x, '+', y);
operation(x, '-', y);
operation(x, '*', y);
operation(x, '/', y);
return 0;
}
void operation(int a, char op, int b) // 사칙연산 함수
{
int result = 0;
switch (op)
{
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
result = a / b;
break;
}
printf("%d %c %d = %d\n", a, op, b, result);
}
< 함수 활용하기 >
> 변수의 사용 범위
1) 지역 변수
(1) 코드 블록 (중괄호( { } )) 내에서만 사용가능
- 코드 블록 실행이 완료되면 할당된 메모리가 해제됨
- 자동 변수 또는 동적 변수라고 할 수 있음
- 변수 선언 시 auto keyword 가 생략 되어 있음
(2) 함수의 매개변수는 지역 변수임
void test(int a, int b)
{
// 매개 변수의 사용 범위
}
(3) 지역 변수 선언 후 초기화하여 사용해야 함
int main()
{
int a; // uninitialized local variable 'a' used → int a = 0;
printf("%d", a);
return 0;
}
(4) 지역 변수 이름의 중복
- 서로 다른 코드 블록에 선언된 변수 이름은 중복이 가능함
- 지역 변수를 사용하는 코드 블록에 선언된 변수가 우선됨
int main()
{
int a = 10;
printf("%d\n", a); // 바깥쪽 코드: 10
if (a == 10)
{
int a = 20;
printf("%d\n", a); // 안쪽 코드: 20
}
}
2) 전역 변수
(1) 소스 파일 전체에서 사용 가능
- 함수 외부에 선언함
- 프로그램이 시작될 때 메모리가 할당되고, 프로그램이 종료될 때 메모리가 해제됨
- 전역 변수를 선언하면 자동으로 0 또 NULL 로 초기화 됨
#include <stdio.h>
int a; // 전역변수 선언(아래 서로 다른 함수에서 동일한 변수 가짐)
void test()
{
a += 20;
printf("%d\n", a);
}
int main()
{
a += 10;
printf("%d\n", a); // 10 출력
test(); // 30 출력
return 0;
}
(2) 전역 변수와 지역 변수 이름 중복
- 지역 변수가 우선됨
#include <stdio.h>
int a; // 전역변수 a (지역 변수 a와 중복)
void test()
{
a += 20;
printf("%d\n", a);
}
int main()
{
int a = 10; // 지역변수 a
printf("%d\n", a); // 전역변수보다 우선되어 10 출력
test(); // 전역변수 a가 대입되어 20 출력
return 0;
}
3) 외부 변수와 외부 함수
- 하나의 프로젝트 내부에 두 개 이상의 소스파일에서 공유하는 변수 또는 함수
#include <stdio.h>
int a; // 외부 전역변수 연결 보냄
extern void test(); // 외부함수 연결 받음
int main()
{
a = 10;
printf("%d\n", a); // 10 출력
test();
return 0;
}
#include <stdio.h>
extern int a; // 외부 전역변수 연결 받음
void test() // 외부 함수 연결 보냄
{
a += 20;
printf("%d\n", a);
}
4) 레지스터 (register) 변수
CPU 의 레지스터 저장공간을 사용하는 변수
- 실행 속도가 빠름
- 지역 변수로만 선언 가능
- 포인터 및 주소 참조 연산자 (&) 사용 못함
- register 키워드 사용하여 선언
#include <stdio.h>
int main()
{
register int a = 10;
printf("%d\n", a);
return 0;
}
5) 정적 (static) 변수
(1) 정적 지역 변수
- 지역 변수 선언 시 static 키워드 지정
- 변수가 선언된 코드 블록 내부에서만 사용 가능
- 프로그램 실행 시 메모리 할당, 프로그램 종료 시 메모리 해제
- 자동 초기화 됨
- 변수 선언과 동시에 초기화하는 명령문은 한번만 실행됨
#include <stdio.h>
void counter()
{
static int cnt = 0; // 첫번째 호출 시 한번만 실행됨
cnt += 10; // 두번째 호출부터는 해당 증감식만
printf("%d\n", cnt);
}
int main()
{
counter(); // 10
counter(); // 20
counter(); // 30
}
(2) 정적 전역 변수
- 전역 변수 선언 시 static 키워드 지정
- 정적 전역 변수가 선언된 소스 파일에서만 사용
- 외부 변수로 사용하지 못함
- 자동 초기화 됨
int a; // 외부 변수 연결 보냄 가능
static int b; // 외부 변수 연결 보냄 불가
int main(){
}
extern int a; // 외부 변수 연결 받음 가능
extern int b; // 외부 변수 연결 받음 불가능
void test(){
}
(3) 정적 함수
- 함수 선언 시 static 키워드 지정
- 정적 함수가 선언된 소스 파일에서만 사용
- 외부 함수로 사용하지 못함
int set (); // 외부 함수 연결 가능
static int get(); // 외부 함수 연결 불가능
int set() {...}
static int get() {...}
extern int set(); // 외부 함수 연결 가능
extern int get(); // 외부 함수 연결 불가능
void test(){
}
> main( ) 함수와 함수 포인터
1) main ( ) 함수
(1) main( ) 함수의 매개변수
- 첫 번째 매개변수 : 두 번째 매개변수 배열 요소의 개수
- 두 번째 매개변수 : 문자열 포인터 배열
#include <stdio.h>
int main(int argc, char* argv[])
// argc 문자열 포인터 배열의 크기
// 배열의 문자열을 지정하여 프로그램 실행
{
// 첫번째 매개변수 argc 변수 값 화면 출력
printf("argc = %d\n", argc);
// argv의 내용을 출력하기 위해 argc 값만큼 반복
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
} // argv 배열 내용을 화면에 출력하면 main 함수의 매개변수 내용을 모두 화면에 출력
return 0; // 프로그램이 정상적으로 종료되었다 의미 운영체제에 전달
}
/*
argc = 1
argv[0] = C:\Users\mnkyu\Desktop\test\teess\x64\Debug\teess.exe
*/
(2) main ( ) 함수의 인수 지정하기
- 비주얼스튜디오 [디버그] - [속성] 실행
- 명령프롬프트에서 [프로젝트 폴더] - [debug 폴더] 이동
2) 함수 포인터
- 함수 포인터 : 함수를 가리키는 포인터 변수
- 함수 포인터 선언 : 가리키고자 하는 함수의 반환 자료형과 매개변수 자료형을 동일하게 선언
int add(int a, int b); // add 함수 원형
int main()
{
int(*p)(int, int);
// add함수 가리키는 함수포인터변수 p 선언
// 매개변수의 변수이름 미지정, 자료형 지정
p = add; // add 함수의 주소를 함수 포인터 p에 저장
int a = (*p)(10, 20); // 함수포인터 p를 이용하여 add함수 호출할 수 있음
}
> main( ) 함수와 함수 포인터 실습
'Language > C & C++' 카테고리의 다른 글
HGC - Chapter 9 exam (0) | 2022.08.29 |
---|---|
C_10. Basic Grammar of Structure (0) | 2022.08.15 |
C_08. Basic Grammar of Pointer (0) | 2022.08.11 |
C_07. Basic Grammar of Array (0) | 2022.08.11 |
C_06. Basic Grammar of Iteration Statement (0) | 2022.08.10 |