본문 바로가기
C언어/C언어

[C언어]함수 매개변수에 함수를 넣으면 순서대로 작동할까?(함수 매개변수의 평가순서)

by Oliver_Candy 2023. 2. 17.

함수-매개변수-평가순서


 함수 매개변수의 평가순서

 

간단한 코드의 실행결과를 맞춰보시라

 [문제] 자주 하는 실수 1

#include <stdio.h>

int add_ten(void)
{
	
    static int number = 0;
    
    number += 10;
    
    return number;
}

int main(void)
{
	
    
    printf("%d %d %d\n", add_ten(), add_ten(), add_ten());
    
    return 0;
}

 

1. 10 20 30

2. 30 20 10

3. 알 수 없음

 

 

 

 

정답은.... 알 수 없음!! 

엥? Visual Stdio에서 돌리니까 30 20 10 나오던데요?

C표준에서는 함수 매개변수 안에 함수를 줄줄이 넣었을 때 어떤 함수부터 호출되는지는 명시하지 않았다.(어떻게 하던지 컴파일러 마음이다)

이런 매개변수 안에 있는 계산들을 누구부터 할지 정하는 것은 평가순서라고 한다.

평가순서는 시퀀스 포인트(sequence point)만이 정한다.

예를 들면 세미콜론(;)이 시퀀스 포인트이다. 그렇기 때문에 C언어가 한 줄 한 줄씩 실행이 된다.

그리고 신기한 것은 시퀀스 포인트에 ||, &&, 삼항연산자(? !)도 포함이 된다.

 

그렇다면 다음 문제를 풀어보자

 자주 하는 실수 2 (평가 순서)

int check_bag = 0;

int checking_bag(void)
{
	
 /* 만약에 가방이 있으면 check_bag 를 1로 바꾸는 로직 */
    check_bag = 1;
    
    return check_bag;
}

int checking_things(void)
{
/* 가방이 있으면 1을 반환하는 로직 */
    if (check_bag == 1) {
    	return 1;
    } else {
    	return 0;
    }
}

int main(void)
{

/* 다른 코드 생략 */
	if ( checking_bag() + checking_things() == 2) {
    	printf("가방안에 물건이 있습니다.\n");
    }
    
    
    return 0;
}

이 코드를  개발한 사람의 로직

  • 메인함수 안에 조건문에서 checking_bag()가 실행이 되고 checking_things()이 실행이 될 거야
  • checking_bag()가 먼저 실행이 돼서 가방이 있으면 check_bag = 1로 하고 check_bag를 반환해
  • 그다음 checking_things() 함수가 실행이 돼서 check_bag가 1인지 체크를 해서 1이면 1을 반환하고 아니면 0을 반환해
  • checking_bag()가 0 이면 checking_things() 도 0이니 조건문이 실행이 안될 거야
  • checking_bag()가 1 이면 checking_things() 도 1이니 조건문이 실행되겠지?

 

 

 

하지만 아까 전에 말한 것처럼 평가순서는 무조건 시퀀스 포인트만이 정하는 것이므로 어느 함수가 먼저 실행이 될지는 모른다.

그래서 checking_things() 함수가 먼저 실행이 돼서 체크를 하니 check_bag가 0이어서 0을 반환하고 checking_bag() 함수가 이후에 실행이 돼서 1을 반환하게 되면 조건문이 실행되지 않게 된다.

즉, checking_things() 함수가 먼저 호출(평가)될 보장이 없다는 뜻이다.

 해결책

두 함수를 두줄에 따로 호출할 것

 


 연산자 우선순위와 평가순서의 관계?

 자주 하는 실수 3

int result = add(num1, num2) + subtract(num1, num2) * divide(num1, num2);

어떤 함수가 먼저 호출(평가)될까?

 

subtract() -> divide() -> add()

add() -> subtract() -> divid()

알 수 없음

 

이 문제의 답은 또 '알 수 없음'이다.

엥? 곱셈부터 계산하고 덧셈계산해야 되니 subtract(), divide() 하고 add()해야 되는 거 아닌가요? 

평가순서랑 연산자 우선순위는 아무런 연관이 없다!

+ * 모두 시퀀스 포인트가 아니다

그렇기에 함수는 아무 순서로 호출해도 상관이 없고 그 결과를 연산자 우선법칙으로 계산하는 것이다.

 

 

 

 정리

  • 한 줄에 있는 피연산자들은 기본적으로 평가순서가 보장 안됨
  • ||, &&, 삼항연산자(? !), ;(세미콜론)은 평가순서가 보장됨(시퀀스 포인트)
  • 연산자 우선법칙이랑 평가순서는 아무런 관련이 없음

 

출처 : POCU Academy COMP2200

댓글