Post

C언어 :: 함수에 관하여

C언어 :: 함수에 관하여

C언어의 핵심인 함수에 대한 이해도를 높일 수 있는 글입니다.

함수란?

gpt에게 “C언어에서 함수란 무엇인가요?” 라는 질문을 하면 다음과 같은 답을 받을 수 있다.

C언어에서 함수란 특정 작업을 수행하는 코드 블록으로, 프로그램의 모듈화와 재사용성을 높이는 역할을 합니다. 함수는 입력값을 받아 처리한 후, 결과값을 반환할 수도 있고, 단순한 동작을 수행할 수도 있습니다.

쉽게 말해 함수란 우리가 입력한 작업을 수행하는 코드 블록이라고 할 수 있겠다. 다만 입력값 또는 출력값이 있을 수도, 없을 수도 있는 것이다.


함수의 구조

함수의 기본적인 구조는 다음과 같다. 그러나 전달인자(=입력 값)가 없거나 반환 값이 없는 경우도 있다. 필요하다면 둘 다 없는 함수를 정의하는 것도 가능하다.

1
2
3
반환형태 함수이름(입력형태) {
    // 몸체
}


즉, 전달인자와 반환 값의 유무에 따라서 함수를 다음의 네가지로 구분할 수 있다.

1. 전달인자 O, 반환 값 O

가장 일반적인 형태의 함수이다.

1
2
3
4
5
6
7
8
9
/*
전달인자: int형 정수 2개
동작: 전달인자를 이용한 덧셈
반환 값: 덧셈 결과
*/
int add(int num1, int num2) {
    int result = num1 + num2;
    return result;
}


2. 전달인자 O, 반환 값 X

반환 값이 없을 때는 void를 명시한다.

1
2
3
4
5
6
7
8
/*
전달인자: int형 정수 1개
동작: 전달인자 출력
반환 값: 없음
*/
void showAddResult(int num) {
    printf("덧셈 결과: %d\n", num);
}


3. 전달인자 X, 반환 값 O

전달인자가 없을 때는 void를 명시하거나, 빈 상태로 둔다.

1
2
3
4
5
6
7
8
9
10
/*
전달인자: 없음
동작: 사용자에게 정수 입력받기
반환 값: 입력받은 정수
*/
int readNum() {
    int num;
    scanf("%d", &num);
    return num;
}


4. 전달인자 X, 반환 값 X

전달인자, 반환 값 없이 특정 동작을 수행할 때 사용하는 형태이다.

1
2
3
4
5
6
7
8
9
/*
전달인자: 없음
동작: 출력
반환 값: 없음
*/
void howToUseThisProgram() {
    printf("두 개의 정수를 입력하시면 덧셈 결과가 출력됩니다.\n");
    printf("입력해 주세요.\n");
}


참고로 return을 생략하지 않고 다음과 같이 작성해도 동일하게 동작한다.

1
2
3
4
5
void howToUseThisProgram() {
    printf("두 개의 정수를 입력하시면 덧셈 결과가 출력됩니다.\n");
    printf("입력해 주세요.\n");
    return;
}


예제

위에서 정의한 함수들을 사용하여 간단한 프로그램을 작성해 보겠다.

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 add(int num1, int num2) {
    return num1 + num2;
}

void showAddResult(int num) {
    printf("덧셈 결과: %d\n", num);
}

int readNum() {
    int num;
    scanf("%d", &num);
    return num;
}

void howToUseThisProgram() {
    printf("두 개의 정수를 입력하시면 덧셈 결과가 출력됩니다.\n");
    printf("입력해 주세요.\n");
}

int main(void) {
    int result, num1, num2;
    howToUseThisProgram();
    num1 = readNum();
    num2 = readNum();
    result = add(num1, num2);
    showAddResult(result);
    return 0;
}


함수의 위치

C언어의 컴파일러는 위에서 아래로 컴파일을 진행하기 때문에 함수 호출 위치에 따라 컴파일 에러를 발생시킬 수 있다.

1
2
3
4
5
6
7
8
9
10
int main(void) {
    int num = 10;
    num = increment(num); // 컴파일 에러 발생
    return 0;
}

int increment(int n) {
    n++
    return n;
}


위와 같은 컴파일 에러를 해소하기 위해서는 두가지 방법이 있다. 함수의 호출보다 정의를 먼저 하거나, 함수의 호출보다 선언을 먼저 하는 것이다. 전자는 위 코드에서 단순히 main()과 increment()의 순서만 변경하면 되며, 후자는 다음과 같이 말그대로 함수의 선언부만 먼저 작성하면 된다.

참고로 함수의 선언은 매개변수의 이름을 생략할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
int increment(int n); // 함수 선언. int increment(int)

int main(void) {
    int num = 10;
    num = increment(num); // 함수 호출
    return 0;
}

int increment(int n) { // 함수 정의
    n++
    return n;
}


지역변수(Local Variable)

  • 선언된 지역 내에서만 유효하다.
  • 지역을 벗어나면 자동으로 소멸된다.
  • 스택(stack)이라는 메모리 영역에 할당된다.
  • 매개변수는 지역변수의 일종이다.

참고로 지역변수에서 말하는 지역이란 중괄호에 의해 형성되는 영역을 뜻한다. 즉 지역변수는 반복문에도 선언이 가능한데, 반복은 중괄호의 진입과 탈출을 반복하면서 이루어지기 때문에 반복이 이뤄질 때마다 지역변수는 메모리상에 할당되고 소멸된다.


전역변수(Global Variable)

  • 프로그램의 시작과 동시에 메모리 공간에 할당되어 종료 시까지 존재한다.
  • 별도의 값으로 초기화하지 않을 경우 0으로 초기화된다.
  • 프로그램 전체 영역에서 접근할 수 있다.

참고로 지역변수와 전역변수의 이름이 같을 경우 지역변수에 우선적으로 접근한다.


static 변수

  • 선언된 함수 내에서만 접근 가능하다.
  • 단 1회 초기화되고 프로그램 종료 시까지 메모리 공간에 존재한다.
  • 별도의 값으로 초기화하지 않을 경우 0으로 초기화된다.
  • 접근 범위를 제한하는 것에 의의가 있다.


register 변수

  • 지역변수에 사용하는 키워드이다.
  • 빈번히 사용하는 변수를 접근이 빠른 레지스터에 저장하도록 컴파일러에게 힌트를 준다.
  • 키워드를 사용한다고 반드시 레지스터에 저장되는 것은 아니며, 컴파일러가 판단 후 결정한다.
This post is licensed under CC BY 4.0 by the author.