1. main()함수의 리턴값
return문을 만나면 함수의 나머지 부분에 상관없이 함수의 실행을 종료하고 호출한 함수로 넘어간다.
main()함수의 경우 return문을 만나면 프로그램이 끝난다. return 문은 기본적으로는 하나의 값만 되돌려주는데 포인터를 사용하면 둘 이상의 값을 return할 수 있다.
main()함수의 리턴값은 프로그램이 끝나면서 OS에 전달되는 값이다.
(프로그램이 정상적으로 종료되면 보통 0을 리턴한다.)
(비정상적으로 종료할 때는 1을 리턴하는 것이 관례이다.)
2. 재귀(recursive)함수
함수가 함수 내에서 자기 자신을 호출할 수 있는데 이것을 재귀 호출(recursive call)이라고 한다.
재귀 호출을 허용하는 함수를 재귀 함수라고 하며 구현하고자 하는 작업이 함수 자신을 순환 반복하여 구현되어질 수 있다면 재귀함수를 이용할 수 있다.
재귀함수는 재귀적 특성을 표현하는 알고리즘에서 쉽고 이해하기 쉬운 문제 해결 방법이다.
하지만 함수의 반복 호출로 인한 시간과 메모리 공간의 효율성이 떨어지는 단점이 존재한다.
(스택오버플로우(stack overflow)주의!)
재귀함수는 반복문을 이용한 함수로 변환이 가능하다.
3. 스택 오버플로우
함수 내부에서 사용하는 변수들은 스택이란 곳에 저장되는데 마련된 스택의 크기를 초과하면 발생하는 문제이다.
함수가 끝나면 스택 영역을 다른 함수에서 사용할 수 있는데 재귀적 호출에서는 재귀함수가 끝나지 않고 계속 재귀적으로 실행되므로 스택에 값이 들어오기만 하고 제거가 되지 않는 것이다.
(7행: 6행의 in값에 따라 sum()함수가 재귀호출을 하므로 자기 자신을 반복해서 호출하게 되는데 실행결과를 보면 in이 4790일 때까지는 정상적으로 수행하지만 그 다음부터는 오류 메시지도 없이 프로그램 살행이 중단된다. 이것을 재귀호출에 의한 스택 오버플로우라한다.)
4. 실매개변수 VS 형식매개변수
함수들 간에 서로 데이터를 교환할 때 사용하는 것을 함수의 매개변수라고 한다.
실매개변수(actual parameter, argument)는 함수를 호출할 때 사용하는 매개변수이다.
형식매개변수(formal parameter, parameter)는 함수 정의에서 사용하는 매개변수이다.
5. 매개변수를 전달하는 방법
C언어에서는 기본적으로 값에 의한 호출(call by value)이다.
실매개변수의 값을 형식매개변수로 전달한다. 이 방법은 실매개변수를 형식매개변수로 전달할 뿐 함수 내부에서 형식매개변수가 변경되더라도 실매개변수는 변경되지 않는다.
형식매개변수가 변하면 실매개변수도 변하게 하려면 포인터를 이용하여 call by reference로 구현해야 한다.
값에 의한 호출 (call by value) |
주소에 의한 호출 (call by reference) |
실매개변수의 값을 형식매개변수로 전달 | 실매개변수의 주소를 형식매개변수로 전달 |
6. 기억클래스(Storage Class)
<지역(local)변수와 전역(global)변수>
변수의 유효범위(scope)란 프로그램 내에서 변수가 사용될 수 있는 범위를 말한다.
C언어에서는 지역과 전역이라는 개념으로 변수가 사용될 수 있는 범위를 지정한다.
지역 변수는 해당 함수나 블록({}) 내에서만 사용할 수 있다. 하지만 전역 변수는 소스 전체에서 사용할 수 있다는 특징을 가지고 있다.
지역 변수와 전역 변수는 변수의 선언 위치에 따라서 결정된다.
7. 기억클래스 : 자동(auto)
가장 많이 사용하는 기억클래스
int형 변수 a를 auto로 선언한다. auto변수의 특징으로는 6가지가 있다.
1. 함수 또는 블록의 내부애서 선언한다.
2. 해당 함수나 블록 내에서만 유효한 지역변수이다.
3. 기억클래스가 명시되지 않고 선언된 변수는 모두 자동 변수이다. 즉, auto는 생략이 가능하다. 그래서 지금까지 기억클래스를 쓰지 않고 사용한 모든 변수는 auto변수이다.
4. 스택 공간을 일시적으로 사용한다.
5. 함수나 블록을 진입하면 기억 영역이 확보되고, 벗어나면 기억 영역은 바로 소거된다. 단, return문으로 리턴된 값은 스택에 복사되어 외부로 전달된다.
6. 초기화는 실행시 이루어지며, 초기화하지 않으면 임의의 값(쓰레기 값, garbage value)을 가진다.
8. 기억클래스: 레지스터(register) 변수
레지스터는 CPU가 연산시 데이터를 임시 저장하는데 사용하는 작고 빠른 기억 장소이다.
int형 변수 a를 register변수로 선언하여 사용한다.
- register int a;
register변수는 auto변수와 동일한 특징을 갖고 있다. 다만 스택이 아니라 CPU내의 레지스터에 저장하여 고속처리가 가능하다. register변수는 정수형, 포인터등 4바이트 데이터만 저장이 가능하다. 두개까지만 선언이 가능하고, 초과된 변수는 auto로 지정된다. 레지스터는 주소가 없으므로 주소 참조가 불가능하다. 매우 단순하면서 엄청난 횟수를 반복할 필요가 있는 루프의 변수를 registe변수로 지정하면 고속처리를 할 수 있다.
<기억클래스 정적(static)변수> (중요!)
int형 변수 a를 정적변수로 선언
- static int a;
static변수의 특징으로는 프로그램이 종료될 때까지 값을 유지한다는 특징이 있고 처음 실행시 한 번만 초기화되고 초기화 값이 없으면 0으로 초기화된다. 또한 스택이 아닌 정적 데이터 영역을 사용하고 지역 static변수는 해당 블록 내에서만 접근이 가능하다.
전역 변수는 기본적으로 static이므로 static키워드가 필요없다.
(static변수는 윈도우즈 프로그래밍할 때 많이 사용하므로 그 특징을 잘 알고 있어야 한다.)
(지역 static변수는 지역 변수로 해당 블록 내에서만 유효하지만, 정적 데이터 영역에자료를 저장하여 프로그램 종료될 때까지 값을 유지
또한 처음 실행시 한 번만 초기화 됨(실행파일에 y는 10이라는 값으로 되어 있어서, 프로그램이 실행하는 순간 y는 10))
9. 기억클래스: extern변수
전역 변수는 함수 외부에 선언되는 변수이며 ㅍ로그램의 모든 부분에서 사용할 수 있다.
10. 기억클래스 정리 표
auto | register | (지역)static | 전역 | |
선언 위치 | 함수(블록)내부 | 함수(블록)내부 | 함수(블록)내부 | 함수 외부 |
유효 범위 | 함수(블록)내부 | 함수(블록)내부 | 함수(블록)내부 | 프로그램 전체 |
파괴 시기 | 함수(블록)종료시 | 함수(블록)종료시 | 프로그램 종료시 | 프로그램 종료시 |
초기값 | 초기화되지 않음 | 초기화되지 않음 | 0으로 초기화 | 0으로 초기화 |
저장 장소 | 스택 | CPU의 레지스터 | 데이터 영역 | 데이터 영역 |
'C언어' 카테고리의 다른 글
[C언어] 배열, 구조체, 포인터 (0) | 2022.06.09 |
---|---|
[C언어] 제어문, 함수 (0) | 2022.05.27 |
[C언어] 제어문 (2) (0) | 2022.05.19 |
[C언어] 제어문 (1) (0) | 2022.05.15 |