본문 바로가기
C/기초(두들낙서)

[C기초] 함수 반환/호출/프로토타입

by Meaning_ 2022. 1. 9.
728x90
반응형

함수의 반환

 

두개의 매개변수 (정수)를 받아 합을 반환하는 함수를 만들어보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
 
//두개의 매개변수(정수)를 받아서 합을 반환
int plus(int a, int b) {
    return a + b;
    
}
 
int main() {
    int sum=plus(34);
    printf("%d\n", sum);
    return 0;
}
cs

plus함수가 return값을 반환하는 것 처럼  int형인 main함수도 값을 반환하는데 항상 0을 반환해준다. 

그래서 위 코드 처럼 return 0;을 써도 되고, 안써도 된다. 안써줘도 자동으로 0을 반환해준다. 

 

그렇다면 함수에 반환값이 여러개 있을 수 있을까?

--> 반환값을 여러개 쓰는건 문법상 틀리지 않다. 하지만 C언어는 리턴을 한번이라도 만나면 그자리에서 바로 종료된다. 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
 
 
int noMeaning() {
    printf("first\n");
    return 1;
    //밑에 있는 값 실행안됨
    //c언어에서는 리턴 한번이라도 만나면 그 자리에서 바로 종료됨.
 
    printf("second\n");
    return 2;
}
 
int main() {
    int a;
    a= noMeaning();
    printf("반환된 값:%d\n", a);
 
    
}
 
cs

이 경우 1까지만 반환되고, 바로 함수가 종료되기 때문에 밑에 2는 출력되지 않는 것이다.


void형 함수를 생각해보면 얘는 반환값이 없는데 어떻게 선언해줘야 할지 의문이 생길것이다.

void함수는 return;으로만 선언해주면 된다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
void noMean() {
    printf("first\n");
    return;
    //밑에 있는 값 실행안됨
    //c언어에서는 리턴 한번이라도 만나면 그 자리에서 바로 종료됨.
 
    printf("second\n");
    return;
}
//void 반환값이 없다
int main() {
    noMean();
 
}
cs

 

 

얘도 return;을 만나기 전인 first만 출력되고 second는 출력되지 않는것을 확인할 수 있다. 

 

 

 

 

 

call by-value, call by-reference

값에 의한 호출, 참조에 의한 호출에 대해 알아볼 것이다. 

 

먼저 call by-value부터 알아보자,

두 정수 a,b를 입력받고 a,b값을 서로 swap하는 프로그램을 만들어보자.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
 
 
int main() {
    int a, b;
    scanf_s("%d%d"&a, &b);
 
 
    int temp;
    temp = a;
    a = b;
    b = temp;
    
 
    printf("a=%d b=%d\n", a, b);
}
cs

a에 2 b에 3을 입력받아 주면 출력값은 a는 3,b는 2가 된다. 

이 코드를 그대로 void형의 함수 swap으로 만들어주면 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
void swap(int x, int y) {
    int temp;
    temp = x;
    x = y;
    y = temp;
    printf("x=%d,y=%d\n", x, y);
    
}
 
int main() {
    int a, b;
    scanf_s("%d%d"&a, &b);
    swap(a, b);
    printf("a=%d b=%d\n", a, b);
}
cs

이렇게 써줄 수 있다.

하지만 이때 매개변수인 x와 y값만 swap될뿐 a와 b값은 서로 swap되지 않는다.

 

왜 이런일이 일어나는 걸까?

우선 swap(a,b)를 하면서 a의 2가 x로 들어가고, b의 3이 y로 들어간다. swap함수가 종료되면서 x랑 y만 바뀔뿐 정작 a,b는 바뀌지 않는다. 이렇게 값이 따로노는걸 값만 넘겨줬다고 한다.

a,b도 값을 swap하게 만들어주려면 포인터를 사용하면된다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
void swap(int *x, int *y) {
    int temp;
    temp = *x;
    *= *y;
    *= temp;
    printf("x=%d,y=%d\n"*x, *y);
    
}
 
int main() {
    int a, b;
    scanf_s("%d%d"&a, &b);
 
    
    swap(&a, &b);
    printf("a=%d b=%d\n", a, b);
}
 
cs

 

 

 

예를 들어  a에 2를 넣어주고 그 주소값을 100번지, b에 3을 넣어주고 그 주소값을 200번지라 하자. 

그러면 x에는 100번지,y에는 200번지가 들어간다.

 

tmp=*x이므로 100번지가 가리키는 값인 2가들어가고*x=*y이므로 *x에는 200번지가 가리키는 값인 3이 들어간다. 사실상 *x가 가리키는 값이 a이기 때문에 a에 3이 들어간다. *y,즉 b에는 tmp인 2가 들어간다.

 

이렇게 포인터를 이용해 a와 b를 바꾸는걸 참조에 의한 호출이라한다. 

매개변수들이 a와 b의 값을 어떠한걸로 바꾸고,저장하는 것을 변수를 참조한다고 한다.

 

프로토타입

함수의 원형을 미리 간단하게 적어주는걸 프로토타입이라 한다.

예를 들어 90도씩 회전하고 일정한 거리만큼 가는 로봇을 프로그래밍한다고 해보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
 
 
void walk(int distance) {
    printf("%dcm를 걸었습니다.\n", distance);
}
 
//돌기
void rotate(int angle) {
    printf("%d도 회전했습니다.\n", angle);
}
 
void drawSquare() {
    for (int i = 0; i < 4; i++) {
        walk(10);
        rotate(90);
    }
}
 
int main() {
    drawSquare();
}
cs

 

 

이 코드의 문제점은 함수들의 순서를 마음대로 조정할 수 없다는 문제점이 있다.

뿐만 아니라 walk함수가 rotate함수를 호출하는데, rotate함수도 walk함수를 호출하려면 당연히 에러가 뜬다.

이때 프로토타입을 사용해줘서 앞에 함수가 어떻게 생겼는지만 정의해주고, 선언은 뒤로 미룰 수 있다.

 

 

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
#include <stdio.h>
 
//걷기
void walk(int );//그냥 함수가 있구나, 그리고 void형에 int매개변수 받는군
//매개변수도 타입만 정의해도 상관없음
 
//돌기
void rotate(int angle);
 
void drawSquare();
 
int main() {
    drawSquare();
}
void walk(int distance) {
    printf("%dcm를 걸었습니다.\n", distance);
}
 
//돌기
void rotate(int angle) {
    printf("%d도 회전했습니다.\n", angle);
}
 
void drawSquare() {
    for (int i = 0; i < 4; i++) {
        walk(10);
        rotate(90);
    }
}
cs

 

void walk(int );  --> 이런식으로 함수의 원형만 밝혀주면 된다. 이러면 컴파일러는 함수의 기능은 몰라도 walk함수가 있다는 것은 알고 있기에 함수의 순서를 바꿔도 문제가 되지 않는다. 뿐만 아니라 매개변수의 자료형만 밝혀줘도 상관없다. 

 

 

프로토타입의 장점

함수안에 함수 호출할때

함수의 선언순서 신경쓰고 싶지 않을때

cpp파일에 어떤 함수가 정의되어있는지 한눈에 파악가능

--> 코드를 간결하고 보기 쉽게 만드는 애 

728x90
반응형

댓글