함수
함수는 코드를 작성하는데 있어 문제를 하나씩 해결하려는 이유와 이후 예상하지 못한 문제가 발생할 시 빠르고 쉽게 해결하기위해 만든다고 볼 수 있습니다. 함수는 입력에 따른 출력이 존재하는 것이라 했으나, 입력(전달인자)가 없거나 출력(반환 값)이 없는 경우도 있습니다.
유형에 따라 함수를 구분하면 전달인자와 반환 값의 존재 유무로 나눌 수 있습니다.
- 전달인자와 반환 값 모두 있는 경우
가장 일반적인 형태의 함수입니다. 이 경우 전달인자와 반환 값 모두 같은 자료형의 변수를 선언해야합니다. 예를 들면 다음과 같습니다.
it Add(int num1, int num2) //int형 함수 Add를 선언하고 int형 전달인자(매개변수)를 받는다.
{
int result = num1 + num2; // 반환 값의 변수도 동일한 int형이다.
return result; // 반환 값
// return num1+num2; 로 작성해도 동일한 결과를 얻을 수 있다.
}
main함수에서 변수에 Add함수를 호출하면 함수의 호출문이 반환 값으로 대체됩니다. 즉, Add함수가 종료되면서 반환된 값이 대입연산을 통해 변수에 저장됩니다.
- 전달인지나 반환 값이 존재하지 않는 경우
void ShowAddResult(int num) // 전달인자만 존재.
{
printf("덧셈결과 출력 %d \n", num);
}
함수 정의에서 반환형이 void로 선언됐습니다. 여기서 void는 '반환하지 않는다'라는 의미입니다. 그래서 함수 몸체에 return문이 존재하지 않습니다.
int ReadNum(void) // 반환 값만 존재.
{
int num;
scanf("%d", &num);
return num;
}
매개변수의 선언 위치에 void 선언이 등장했습니다. 여기서 void는 '인자를 전달하지 않는다'라는 의미입니다. 이처럼 void를 이용해 전달인자와 반환 값을 받을지 말지를 선언해 함수를 만들 수 있습니다.
지금까지 함수를 만드는 방법에 대해 확인했습니다. 그러면 이렇게 만든 함수의 위치를 결정할 때 주의를 기울여야 합니다.
int main(void)
{
int num = 2;
num = Incement(num);
retunr 0;
}
int Increment(int n)
{
return n++;
}
이와 같이 코드를 작성하면 main함수에서 Incement함수를 본적이 없다면서 에러가 발생합니다. C언어는 절차지향 프로그래밍 언어로 위에서부터 순차적으로 코드를 읽어나갑니다. 그렇기때문에 main문 앞에 함수의 선언을 넣어줘야합니다.
int Increment(int n); //함수의 선언
int mian(void)
{
......
}
int Increment(int n) //함수의 정의
{
.....
}
main문 앞에서 함수의 선언이 이루어지고 이후에 선언된 함수의 정의가 나옵니다. 함수의 정의를 먼저 한 이후 main문을 작성해도 되지만, 코드는 혼자만 볼 것이 아니라 여러 사람이 보는 것으로 일반적인 경우를 따르는 것이 좋습니다.
변수
변수는 선언되는 위치에 따라 '전역변수'와 '지역변수'로 나뉩니다. 이 둘의 차이는 메모리상에 존재하는 기간, 변수에 접근할 수 있는 범위에 있습니다.
- 지역변수
여기서 지역은 중괄호에 의해 형성되는 영역을 뜻합니다.
int SimpleFuncOne(void) // void에 매개변수가 들어가면 이 또한 지역변수이다
{
int num = 10; // 지역변수 num
.....
}
이렇게 중괄호 안에서 선언된 변수를 지역변수라 부릅니다. 따라서 num은 중괄호를 벗어난 구간에서 호출하면 에러가 발생합니다. 지역변수는 해당 선언문이 실행될 때 메모리 공간에 할당됐다가, 선언문이 존재하는 함수가 반환을 하면(종료) 메모리 공간에서 소멸됩니다. 즉, 이전에 함수를 호출해서 생긴 값은 반환과 동시에 모두 사라집니다. 그래서 지역변수가 선언된 지역을 제외한 곳에서 또 다른 지역변수를 같은 변수로 선언해도 무방합니다.
- 전역변수
전연벽수는 어디서든 접근이 가능한 변수로써 지역변수와 달리 중괄호 내에 선언되지 않습니다. 따라서 전역변수는 프로그램의 시작과 동시에 메모리 공간에 할당되어 종료 시까지 존재하며, 별도의 값으로 초기화하지 않으면 0으로 초기화되며, 프로그램 전체 영역 어디서든 접근이 가능합니다.
#include <stdio.h>
void Add(int val);
int num; // 전역변수는 기본 0으로 초기화된다.
....
전역변수의 선언은 이렇게 진행합니다. 만약 전역변수와 동일한 이름의 지역변수가 선언되면 해당 지역 내에서 전역변수가 가려지고, 지역변수로의 접근이 이루어집니다. 하지만 이런 상황 자체는 만들지 않는 것이 좋습니다. 에러 발생 시 문제를 찾기도 쉽지않아 코드가 엉키면 해결하는데 오랜 시간이 걸립니다.
전역변수는 지역변수에 비해 상당히 편리한듯하지만, 사용을 최대한 제한하는 것이 좋습니다. 전역변수는 프로그램의 구조를 복잡하게 만드는 주범이기 때문입니다. 앞서 설명했듯 전역변수는 프로그램의 시작과 동시에 생성돼 종료될 때까지 존재한다 했습니다. 이는 마치 지금 하지않는 작업을 책상에 펼쳐둔거와 같습니다.
- 추가적인 변수
static 변수
지역 변수의 휘발되는 특징은 static 선언을 통해 막을 수 있습니다. 지역변수 선언 시 static를 붙이면 지역변수도 전역변수처럼 프로그램 종료 시까지 메모리에 저장됩니다. static (지역)변수는 전역변수로 쉽게 대체가 가능합니다. 하지만 static (지역)변수는 전역변수보다 안정적이므로, 가능하다면 전역변수를 static (지역)변수로 대체하면 프로그램의 안전성을 높일 수 있습니다.
register 변수
지역변수의 또 다른 추가 선언입니다. static함수와 같이 선언을 할 수 있습니다. 이는 변수가 CPU 내에 존재하는 '레지스터'라는 메모리 공간에 저장될 확률이 높아집니다. 레지스터는 CPU내에 존재하는 매우 작은 메모리입니다. 하지만 CPU내에 존재하기 때문에 이 메모리에 저장된 데이터를 대상으로 하는 연산은 매우 빠릅니다. 하지만 레지스터의 최종 결정은 컴파일러가 내립니다. 또한 이는 지역변수만 가능합니다.
재귀함수
재귀함수란 같은 함수 내에서 자기 자신을 다시 호출하는 함수를 의미합니다.
void Recursive(void)
{
printf("Recursuve call! \n");
Recursuve(); // 자기 자신을 재 호출
}
마치 에러가 날듯하지만 이는 가능하다. 쉽게 이해를 돕기위해 설명하면 Recursive함수 내에서 Recursuve의 복사본을 호출하는 것이다.
'배울 것들 > 언어' 카테고리의 다른 글
C프로그래밍 10/? 포인터 (0) | 2018.11.21 |
---|---|
C프로그래밍 9/? 배열 (0) | 2018.11.20 |
C프로그래밍 7/? 조건문 (0) | 2018.11.19 |
C프로그래밍 6/? 반복문 (0) | 2018.11.19 |
C프로그래밍 5/? 자료형 (0) | 2018.11.13 |